专栏文章

题解:UVA10359 Tiling

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

文章操作

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

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

思路

首先,很容易看出本题考查的算法为动态规划。
dpidp_i 为摆出 2×n2\times n 的长方形的方案数,考虑如何转移。
不难发现 2×n2\times n 的长方形既可以由 2×(n1)2\times(n-1)2×12\times 1 的长方形拼出,也可以由 2×(n2)2\times(n-2) 与两块 1×21\times 22×12\times 1 的长方形拼出。
dpi=2×dpi2+dpi1dp_i=2\times dp_{i-2}+dp_{i-1}

注意事项

本题答案的值可能极大,需要使用高精度加法与高精度乘法。(其实可以不用高精度乘法)
注:为了追求效率,我使用了快速傅里叶变换以实现高精乘。

代码(码风猎奇)

CPP
#include<bits/stdc++.h>
using namespace std;
const int N=257,M=1007;
const double Pi=acos(-1.0);
int n,lg[M];
string dp[N];

string High_precision_addition(string a,string b){
	int ans[max(a.size(),b.size())+7]={0};
	if(a.size()>b.size())
		swap(a,b);
	while(a.size()<b.size())
		a='0'+a;
	for(int i=0;i<a.size();++i)
		ans[i]=(a[a.size()-i-1]-'0'+b[a.size()-i-1]-'0');
	for(int i=0;i<a.size();++i){
		ans[i+1]+=ans[i]/10;
		ans[i]%=10;
	}
	string res="";
	if(ans[a.size()])
		res+=char(ans[a.size()]+'0');
	for(int i=a.size()-1;i>=0;--i)
		res+=char(ans[i]+'0');
	return res;
}

void Fast_Fourier_Transform(int limit,complex<double> *a,int type){
	if(limit==1)
		return;
	complex<double> 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];
	}
	Fast_Fourier_Transform(limit>>1,a1,type);
	Fast_Fourier_Transform(limit>>1,a2,type);
	complex<double> w{1,0};
	complex<double> wn{cos(2*Pi/limit),type*sin(2*Pi/limit)};
	for(int i=0;i<limit>>1;++i,w*=wn){
		a[i]=a1[i]+a2[i]*w;
		a[i+(limit>>1)]=a1[i]-a2[i]*w;
	}
}

string High_precision_multiplication(string a,string b){
	complex<double> f[1<<(lg[max(a.size(),b.size())]+1)];
	complex<double> g[1<<(lg[max(a.size(),b.size())]+1)];
	int ans[M]={0};
	for(int i=1;i<=a.size();++i)
		f[i-1]=a[a.size()-i]-'0';
	for(int i=1;i<=b.size();++i)
		g[i-1]=b[b.size()-i]-'0';
	int lt=1;
	while(lt<=a.size()+b.size()-1)
		lt<<=1;
	Fast_Fourier_Transform(lt,f,1);
	Fast_Fourier_Transform(lt,g,1);
	for(int i=0;i<=lt;++i)
		f[i]*=g[i];
	Fast_Fourier_Transform(lt,f,-1);
	for(int i=0;i<=a.size()+b.size()-1;++i)
		ans[i]=(int)(f[i].real()/lt+0.5);
	for(int i=0;i<a.size()+b.size()-1;++i){
		ans[i+1]+=ans[i]/10;
		ans[i]=ans[i]%10;
	}
	string res="";
	bool flg=true;
	for(int i=a.size()+b.size()-1;i>=0;--i){
		if(flg&&!ans[i])
			continue;
		else{
			flg=false;
			res+=char(ans[i]+'0');
		}
	}
	return res;
}

int main(){
	dp[0]="1",dp[1]="1",dp[2]="3";
	for(int i=2;i<M;++i)
		lg[i]=lg[i>>1]+1;
	for(int i=3;i<=250;++i)
		dp[i]=High_precision_addition(dp[i-1],
		High_precision_multiplication("2",dp[i-2]));
    while(cin>>n)
		cout<<dp[n]<<"\n";
	return 0;
}

评论

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

正在加载评论...