码迷,mamicode.com
首页 > 其他好文 > 详细

poj 2506 Tiling(高精度)

时间:2015-10-11 16:45:52      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

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 }
View Code

 

贴上一位大神的代码如下:

技术分享
 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 }
View Code

 

 

poj 2506 Tiling(高精度)

标签:

原文地址:http://www.cnblogs.com/cxbky/p/4869393.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!