专栏文章

题解:UVA10359 Tiling

UVA10359题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipsyuca
此快照首次捕获于
2025/12/03 17:26
3 个月前
此快照最后确认于
2025/12/03 17:26
3 个月前
查看原文

UVA10359 Tiling 题解

FFT 好题
易发现可用 dp 求解,设 f(x)f(x) 为拼出长为 22 的图形的方案数。
题目描述了要拼成一个 2×n2×n 的图案,有以下 33 种方案:
  • 在一个 2×(n1)2×(n−1) 的矩阵上增加一个 2×12×1 的图形。
  • 在一个 2×(n2)2×(n−2) 的矩阵上增加一个 2×22×2 的图形。
  • 在一个 2×(n2)2×(n−2) 的矩阵上增加一个 2×12×1 的图形。
所以易推出 f(x)=f(x1)+2×f(x2)f(x)=f(x-1)+2×f(x-2)
由于每次至少乘 22 所以需要用高精度。
在乘 22 的时候可以用 FFT 解决。

Code:

CPP
//f[i]=f[i-1]+2*f[i-2]
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N=1<<22;
const double Pi=acos(-1.0); 
int aa[1000000],bb[1000000],anss[1000000];
string add(string s1,string s2){
	memset(anss,0,sizeof(anss));
	memset(aa,0,sizeof(aa));
	memset(bb,0,sizeof(bb));
	for(int i=0;i<s1.size();i++) aa[i+1]=s1[i]-'0';
	for(int i=0;i<s2.size();i++) bb[i+1]=s2[i]-'0';
	reverse(aa+1,aa+s1.size()+1);
	reverse(bb+1,bb+s2.size()+1);
	int len=max(s1.size(),s2.size());
	for(int i=1;i<=len;i++){
		anss[i]+=aa[i]+bb[i];
		anss[i+1]+=anss[i]/10;
		anss[i]%=10;
	}
	bool flag=0;
	if(anss[len+1]!=0) flag=1;
	string res="";
	for(int i=len+flag;i>=1;i--) res+=char(anss[i]+'0');
	return res;
}
struct complex{
	double x,y;
	complex (double xx=0,double yy=0){x=xx,y=yy;}
}a[N],b[N];
complex operator + (complex a,complex b){return complex(a.x+b.x,a.y+b.y);} 
complex operator - (complex a,complex b){return complex(a.x-b.x,a.y-b.y);} 
complex operator * (complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
void FFT(int limit,complex *a,int type){
	if(limit == 1) return;
	complex a1[limit>>1],a2[limit>>1];
	for(int i=0;i<limit;i+=2)
		a1[i>>1]=a[i],a2[i>>1]=a[i+1];
	FFT(limit>>1,a1,type);
	FFT(limit>>1,a2,type);
	complex Wn=complex(cos(2.0*Pi/limit) , type*sin(2.0*Pi/limit)),w=complex(1,0);
	for(int i=0;i<(limit>>1);i++,w=w*Wn) 
	    a[i]=a1[i]+w*a2[i],
	    a[i+(limit>>1)]=a1[i]-w*a2[i]; 
} 
int n,m,ans[N];
string mul(string s1,string s2){
	memset(ans,0,sizeof ans);
	n=s1.size(),m=s2.size(); 
	reverse(s1.begin(),s1.end());
	reverse(s2.begin(),s2.end());
	for(int i=0;i<n;i++) a[i].x=s1[i]-'0';
	for(int i=0;i<m;i++) b[i].x=s2[i]-'0';
	int limit=1;while(limit<=n+m-2) limit<<=1;
	FFT(limit,a,1);
	FFT(limit,b,1);
	for(int i=0;i<=limit;i++)
	    a[i]=a[i]*b[i];
	    FFT(limit,a,-1);
	for(int i=0;i<=n+m-1;i++)
		ans[i]=(int)(a[i].x/limit+0.5);
	for(int i=0;i<n+m-1;i++){
		ans[i+1]+=ans[i]/10;
		ans[i]%=10;
	}
	int flag=1;
	string res="";
	for(int i=n+m-1;i>=0;i--){
		if(flag && ans[i]==0) continue;
		res+=char(ans[i]+'0');
		flag=0;
	}
	return res;
}
string dp[255];
int main(){
	string sss="2";
	for(int i=0;i<=250;i++) dp[i]="0";
	dp[0]="1",dp[1]="1",dp[2]="3";
	for(int i=3;i<=250;i++){
		string tmp=add(dp[i-2],dp[i-2]);
		dp[i]=add(dp[i-1],tmp);
	}
	int q;
	while(cin>>q){
		cout<<dp[q]<<endl;
	}
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...