洛谷P1255数楼梯(大数,高精度加法)

题目链接:https://www.luogu.org/problemnew/show/P1255

 

这题挺有意思

首先麻烦的一点,要推出方案数:f[n]=f[n-1]+f[n-2]。

然后还不算完,大数运算开始

long long,unsigned long long,60分

 

普通高精大数加法过了,但1400ms

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <cmath>
 7 using namespace std;
 8 typedef long long ll;
 9 typedef unsigned long long ull;
10 const int maxn=1e6+5;
11 char a[maxn],b[maxn],d[maxn];
12 int c[maxn];
13 
14 int zfs(char c)
15 {
16     if(c==0) return 0;
17     else if(c>='0' && c<='9') return c-48;
18     else return c-65+10;
19 }
20 
21 void Add(int len1,int len2)
22 {
23     //交换工作,倒序
24     int p=-1;
25     for(int i=len1-1;i>=0;i--) d[++p]=a[i];
26     for(int i=0;i<=len1-1;i++) a[i]=d[i];
27     p=-1;
28     for(int i=len2-1;i>=0;i--) d[++p]=b[i];
29     for(int i=0;i<=len2-1;i++) b[i]=d[i];
30 
31     //模拟计算
32     int len=max(len1,len2);
33     for(int i=0;i<=len-1;i++)
34     {
35         int x=zfs(a[i]),y=zfs(b[i]);
36         c[i]+=x+y;
37         while(c[i]>=10)
38         {
39             c[i]-=10;
40             c[i+1]+=1;
41         }
42     }
43 
44     //更新操作,重新赋值
45     p=-1;
46     for(int i=len2-1;i>=0;i--) a[++p]=b[i];
47     p=-1;
48     if(c[len]!=0) b[++p]=c[len]+48;
49     for(int i=len-1;i>=0;i--) b[++p]=c[i]+48;
50     memset(c,0,sizeof(c));
51 
52     //输出
53     if(c[len]!=0) cout<<c[len];
54     for(int i=len-1;i>=0;i--) cout<<c[i];
55     cout<<endl;
56 
57 }
58 
59 int main()
60 {
61     ios::sync_with_stdio(false); cin.tie(0);
62 
63     cin>>n;
64     a[0]='1';
65     b[0]='2';
66     if(n==0) { cout<<'0'<<endl; return 0; }
67     if(n==1) { cout<<'1'<<endl; return 0; }
68     if(n==2) { cout<<'2'<<endl; return 0; }
69     for(int i=3;i<=n;i++)
70     {
71         int len1=strlen(a),len2=strlen(b);
72         Add(len1,len2);
73     }
74 
75     cout<<b<<endl;
76 
77     return 0;
78 }

 

大数加法的一个技巧:

不直接输入运算数时,最好用int数组(这时候可以一个一个存),省去了字符转换的时间

要直接输入运算数时,只能用char数组输入(int多位会错没法计算)

int数组,1300ms(就是交换值更新下一轮的时间太大)

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <cmath>
 7 using namespace std;
 8 typedef long long ll;
 9 typedef unsigned long long ull;
10 const int maxn=1e6+5;
11 int a[maxn],b[maxn];
12 int c[maxn];
13 int len=1;
14 int n;
15 
16 void Add()
17 {
18     //计算
19     for(int i=0;i<=len-1;i++)
20     {
21         c[i]+=a[i]+b[i];
22         while(c[i]>=10)
23         {
24             c[i]-=10;
25             c[i+1]+=1;
26         }
27     }
28     if(c[len]) len++;
29 
30     //更新为了下次轮回(应该就是这里交换很费时间没错了!想办法不要交换用别的方法代替!)
31     for(int i=0;i<=len-1;i++) a[i]=b[i];
32     for(int i=0;i<=len-1;i++) b[i]=c[i];
33     memset(c,0,sizeof(c));
34 }
35 
36 int main()
37 {
38     ios::sync_with_stdio(false); cin.tie(0);
39 
40     cin>>n;
41     if(n==0) { cout<<'0'<<endl; return 0; }
42     if(n==1) { cout<<'1'<<endl; return 0; }
43     if(n==2) { cout<<'2'<<endl; return 0; }
44     a[0]=1;
45     b[0]=2;
46     for(int i=3;i<=n;i++)
47     {
48         Add();
49     }
50 
51     if(b[len]) cout<<b[len];
52     for(int i=len-1;i>=0;i--) cout<<b[i];
53     cout<<endl;
54 
55     return 0;
56 }

 

另一种很不错的大数加法写法107ms(其实就是用二维数组优化了上面的,不用再每轮交换更新赋值了!)

思路大概是用数组f[k][j]来存储走k个阶梯所用的步数 最后循环输出

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <cmath>
 7 using namespace std;
 8 typedef long long ll;
 9 typedef unsigned long long ull;
10 const int maxn=1e6+5;
11 int c[maxn];
12 int f[5005][5005];
13 int len=1;
14 int n;
15 
16 
17 void Add(int k)
18 {
19     //计算
20     for(int i=1;i<=len;i++)
21     {
22         f[k][i]+=f[k-1][i]+f[k-2][i];
23         while(f[k][i]>=10)
24         {
25             f[k][i]-=10;
26             f[k][i+1]+=1;
27         }
28     }
29 
30     if(f[k][len+1]) len++;
31 
32 }
33 
34 int main()
35 {
36     ios::sync_with_stdio(false); cin.tie(0);
37 
38     cin>>n;
39     if(n==0) { cout<<'0'<<endl; return 0; }
40     if(n==1) { cout<<'1'<<endl; return 0; }
41     if(n==2) { cout<<'2'<<endl; return 0; }
42     f[1][1]=1; f[2][1]=2;
43     for(int i=3;i<=n;i++)
44     {
45         Add(i);
46     }
47 
48     for(int i=len;i>=1;i--) cout<<f[n][i];
49     cout<<endl;
50 
51     return 0;
52 }

 

完。

posted @ 2018-10-16 12:09  RedBlack  阅读(631)  评论(0编辑  收藏  举报