杭电1041

题意:原本是1的字符经一步变化会变成01,原本是0的字符经一步变化变成10,初始状态是1,问经过n步之后有多少段连续的0.

 
Analyse:
找规律:
n   字符串                      连续0
0   1                          0
1   01                        0
2   1001                         1
3   01101001                     1
4   1001011001101001                3
5   01101001100101101001011001101001     5
好像由第四项开始,有这样的规律:a[n]=a[n-1]+2*a[n-2],如果是这样的话,它比Fibonacci数列增长得还快,肯定是个大数问题。2*a[n-2]的计算我就直接连续加两次a[n-2]来实现了。大数的储存方式我还是选择了用int数组,每三位放入一个int。之前大数相加的方法我一开始先把sum1[],sum2[]都刷零,然后一直由sum1[0]一直加到sum1[N-1],中间有无数次0和0的相加,效率十分低(毕竟水平低,能AC就算了)。但是这次无谓的动作重复太多,交上去就Time Limit Exceeded了,必须删去无谓的环节,于是定义一个digit整数来记录sum1的位数(每用一个int来储存就算一位),加法去到i==digit-1时要判断有没有进位(carry),若carry==0就跳出循环,否则digit++。
View Code
 1 #include<stdio.h>
2 #define DIGITNUM 150
3 int add(int a[],int DigitA,int b[])
4 {
5 //This method add a and b.The result will be stored in array a[]. Initially, a[] should be larger than b[].
6 int i;
7 int c[DIGITNUM],carry=0;
8 for(i=0;i<DigitA;i++)
9 {
10 c[i]=a[i]+b[i]+carry;
11 carry=c[i]/1000;
12 c[i]%=1000;
13 if(DigitA-1==i)
14 {
15 if(carry==0)
16 break;
17 else
18 DigitA++;
19 }
20 }
21 for(i=0;i<DigitA;i++)
22 a[i]=c[i];
23 return DigitA;
24 }
25 int main(void)
26 {
27 int sum1[DIGITNUM],sum2[DIGITNUM],temp[DIGITNUM];
28 int n,i;
29 int Digit2,Digit1;
30 while(scanf("%d",&n)==1)
31 {
32 for(i=0;i<DIGITNUM;i++)
33 sum1[i]=sum2[i]=0;
34 if(n==1)
35 printf("0\n");
36 else if(n==2 || n==3)
37 printf("1\n");
38 else
39 {
40 sum1[0]=1;
41 sum2[0]=1;
42 n-=3;
43 Digit2=1;
44 while(n--)
45 {
46 for(i=0;i<Digit2;i++)
47 temp[i]=sum2[i];
48 Digit1=Digit2;
49 Digit2=add(sum2,Digit2,sum1);
50 Digit2=add(sum2,Digit2,sum1);
51 for(i=0;i<Digit1;i++)
52 sum1[i]=temp[i];
53 }
54 i=Digit2-1;
55 printf("%d",sum2[i--]);
56 for(;i>=0;i--)
57 printf("%03d",sum2[i]);
58 printf("\n");
59 }
60 }
61 return 0;
62 }
原文地址:https://www.cnblogs.com/ZShogg/p/2398135.html