题目大意:一个序列包含0,1,初始为1,计算机依照一下规则产生字符串:将0变为10,将1变为01,如果输入值为n,就反复执行上述步骤n次,求最后的字符串中航油多少组两个连在一起的‘0’;n:(1<n<=1000)
题目分析:对于输入的3:
0:1
1:01
2:1001
3:01101001
第三步产生的序列只有一处出现相邻的两个0,所以结果为1,当n为2的时候也是只有一组。
由于每次执行后,字符串都会变为原来的2倍,所以输入n的时候,最终字符串的长度为2^n。而n最大为1000,2^1000是个非常大的数字。
可以写一个简单的程序,先求出较小的一部分结果,看能不能找出规律。
n=1: 0
n=2: 1
n=3: 1
n=4: 3
n=5: 5
n=6: 11
n=7: 21
n=8: 43
n=9: 85
n=10: 171
n=11: 341
n=12: 683
n=13: 1365
n=14: 2731
n=15: 5461
从第一项开始,把相邻两项加起来
0 + 1 = 1
1 + 1 = 2
1 + 3 = 4
3 + 5 = 8
5 + 11 = 16
11 + 21 = 32
21 + 43 = 64
43 + 85 = 128
85 + 171 = 256
可以发现结果都是2^k,就是说有递推公式了 a(k+1)+ak=2^(k-1) 即:a(k+1)=2^(k-1)-ak,分别求出k=1,2,3……的时候an
k=1: a2=2^0-a1=2^0
k=2: a3=2^1-a2=2^1-2^0
k=3: a4=2^2-a3=2^2-2^1+2^0
k=4: a5=2^3-a4=2^3-2^2+2^1-2^0
k=5: a6=2^4-a5=2^4-2^3+2^2-2^1+2^0
k=6: a7=2^5-a6=2^5-2^4+2^3-2^2+2^1-2^0
当k=2i+1时 可得出 ak=(2^(k-1)-1)/3
当k=2i时 可得出 ak=(2^(k_1)+1)/3
合并后即为: ak=floor(2^(n-1)+1)/3) 但是随着n的增大,2^n会超范围,当n=1000时,有301位
进一步找规律: k=4: a5=2^3-a4=2^3-2^2+2^1-2^0=2(2^2-2^1+2^0)-2^0
k=5: a6=2^4-a5=2^4-2^3+2^2-2^1+2^0=2(2^3-a4=2^3-2^2+2^1-2^0)+2^0
k=6: a7=2^5-a6=2^5-2^4+2^3-2^2+2^1-2^0=2(2^4-a5=2^4-2^3+2^2-2^1+2^0)-2^0
可以发现: a5=2*a4-2^0 a6=2*a5+2^0 a7=2*a6-2^0 所以可得递推公式: a(k+1)=2*ak-(-1)^k
利用二维数组把结果存起来,输出的时候根据下标输出即可
#include<stdio.h> #include<string.h> int main() { char t[1002][302]={"0","0"}; int n,v,i; for(n=1,v=1;n<1000;) { for(i=0;t[n][i]||v;i++,v/=10) { t[n+1][i]=(v+=t[n][i]*2%48)%10+48; } v=n%2?-1:1; strrev(t[n++]); //翻转字符串,阅读时候顺序刚好相反 } while(scanf("%d",&n)!=EOF) { puts(t[n]); } return 0; }