Description
In how many ways can you tile a 2xn rectangle by 2x1 or 2x2 tiles?
Here is a sample tiling of a 2x17 rectangle.
Input
Input is a sequence of lines, each line containing an integer number 0 <= n <= 250.
Output
For each line of input, output one integer number in a separate line giving the number of possible tilings of a 2xn rectangle.
Sample Input
2 8 12 100 200
Sample Output
3 171 2731 845100400152152934331135470251 1071292029505993517027974728227441735014801995855195223534251 刚开始没推出来,还是看了Discuss才知道递推公式是:f[n]=f[n-1]+2*f[n-2],推论方法如下:
首先,无论任何一种方案,最左边的要么是一根竖的,要么是两根横的,要么是一个方的,对吧?所以: 当是一根竖时剩下的方案数是OPT[i-1] 当是两根横时剩下的方案数是OPT[i-2] 当是一个方时剩下的方案数是OPT[i-2] 故OPT[i]=OPT[i-1]+2*OPT[i-2] 转化为二阶齐次常系数线性方程为: f(n-2)-f(n-1)-2f(n-2)=0 其特征方程是: x^2-x-2=0 解得特征方程的根式:x=-1 或 x=2 故得 f(n)=a*(-1)^n+b*2^n 将f(0)=1,f(1)=1的值代入,解得f(n)=1/3*(-1)^n+2/3*2^n 可简化为: if(n%2==0) opt[n]=(2^(n+1)+1)/3 else opt[n]=(2^(n+1)-1)/3不要问我为什么,我也不知道。然后尝试着自己写,于是乎就把自己绕进去了,看了大神的代码才知道什么叫巧妙。。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 struct pos 6 { 7 int a[1500]; 8 int len; 9 } path[300]; 10 void c2(pos &x) //乘2操作 11 { 12 int len=x.len; 13 for(int i=1; i<=len; i++) 14 x.a[i]*=2; 15 for(int i=1; i<=len; i++) 16 { 17 if(x.a[i]>9) 18 { 19 x.a[i]-=10; 20 x.a[i+1]++; 21 } 22 } 23 if(x.a[len+1]!=0) 24 x.len++; 25 } 26 void add(pos &a,pos b,pos c)/*加操作*/ 27 { 28 int Max=max(b.len,c.len); 29 for(int i=1; i<=Max; i++) 30 a.a[i]=b.a[i]+c.a[i]; 31 for(int i=1; i<=Max; i++) 32 { 33 if(a.a[i]>9) 34 { 35 a.a[i]-=10; 36 a.a[i+1]++; 37 } 38 } 39 if(a.a[Max+1]!=0) 40 a.len=Max+1; 41 else 42 a.len=Max; 43 } 44 int main() 45 { 46 int n; 47 while(cin>>n) 48 { 49 memset(path,0,sizeof(path)); 50 path[0].a[1]=1; 51 path[1].a[1]=1; 52 path[0].len=path[1].len=1; 53 for(int i=2; i<=n; i++) 54 { 55 c2(path[i-2]); 56 add(path[i],path[i-1],path[i-2]); 57 } 58 for(int i=path[n].len; i>=1; i--) 59 cout<<path[n].a[i]; 60 cout<<endl; 61 } 62 return 0; 63 }
贴上一位大神的代码如下:
1 #include <iostream> 2 #define base 100000000 3 int a[251][12]; 4 int main(int argc, char** argv) { 5 a[0][0]=a[1][0]=1; 6 for(int i=2;i<=250;i++){ 7 for(int j=0;a[i-1][j];j++){ 8 a[i][j]+=a[i-1][j]+2*a[i-2][j]; 9 if(a[i][j]>=base){ 10 a[i][j+1]+=a[i][j]/base; 11 a[i][j]%=base; 12 } 13 } 14 } 15 int n; 16 while(~scanf("%d",&n)){ 17 int j; 18 for(j=0;a[n][j];j++); 19 j--; 20 printf("%d",a[n][j--]); 21 while(j>=0) 22 printf("%08d",a[n][j--]); 23 printf("\n"); 24 } 25 return 0; 26 }
时间: 2024-10-09 06:21:31