解题报告:这题的意思是一开始电脑中有一个1,现在定义如下规则,每经过一个步骤之后,一个1可以变为01,一个0可以变为10,所以一开始的1经过第一步的变换之后就变为01,然后01经过第二步的变换之后就变成1001,...........,现在要做的就是让你确定经过n步操作之后,里面有多少个连续的00.
我们可以这样推理,00可以经过什么样的排列得到,也就是将00反着推回去,00的上一步就是01,并且只能是01,然后01的上一步可以是一个1,也可以是00,所以地推的公式也出来了,第n步之后00的个数就是dp[n] = dp[n-2] + 2^(n-3) (是2的n-3次方),因为dp[n-2]就是等于往前数的第二个的00的个数,然后2(n-3)就是往前数第二个的1的个数,因为第n项有2^n个数字,并且每一项的0和1的数量都是相等的,所以第n项前面两项的1的个数就是2^(n-3)。然后要注意的就是因为n最大是1000,数字会非常非常大,甚至还没有任何一种数据类型可以存储,所以就要用数组模拟,用数组模拟就涉及到了大数相加的问题,所以再写一个大数相加的函数然后再打表就可以了。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<iostream> 5 char dp[1005][505] = {"0","0","1","1"}; 6 char* add(char *x,char *y) { 7 int a[505],b[505],c[505]; 8 int l1=strlen(x); 9 int l2=strlen(y); 10 memset(a,0,sizeof(a)); 11 memset(b,0,sizeof(b)); 12 memset(c,0,sizeof(c)); 13 int j=0; 14 for(int i=l1-1;i>=0;--i) 15 a[j++]=(int )x[i]-'0'; 16 j=0; 17 for(int i=l2-1;i>=0;--i) 18 b[j++]=(int )y[i]-48; 19 int l=std::max(l1,l2); 20 for(int i=0;i<l;++i) { 21 c[i]=c[i]+a[i]+b[i]; 22 c[i+1]+=c[i]/10; 23 c[i]%=10; 24 } 25 if(c[l]!=0) 26 l++; 27 char dd[505]; 28 for(int i = 0;i<l;++i) 29 dd[i] = c[l-i-1]+'0'; 30 dd[l] = NULL; 31 return dd; 32 } 33 34 void dabiao() { 35 char c[505] = "2"; 36 for(int i = 4;i<=1000;++i) { 37 strcpy(dp[i],add(dp[i-2],c)); 38 strcpy(c,add(c,c)); 39 } 40 } 41 int main() { 42 int n; 43 dabiao(); 44 while(scanf("%d",&n)!=EOF) 45 printf("%s ",dp[n]); 46 return 0; 47 }