题目大意:一个序列包含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

    利用二维数组把结果存起来,输出的时候根据下标输出即可

    

View Code
#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;
}
posted on 2012-05-01 18:22  pcoda  阅读(176)  评论(0编辑  收藏  举报