问题描述
我们要求找出具有下列性质数的个数(包含输入的自然数n):
先输入一个自然数n(n<=1000000),然后对此自然数按照如下方法进行处理:
1.          不作任何处理;
2.          在它的左边加上一个自然数,但该自然数不能超过原数的一半;
3.          加上数后,继续按此规则进行处理,直到不能再加自然数为止.
样例: 输入: 6
           满足条件的数为 6 (此部分不必输出)
                          16
                          26
                         126
                          36
                         136
输出: 6

【算法的改进】

一.递推式的改进

输入数据要求n最大规模达到1000000。此时,O(n2)的算法在n较大时,必定超时。

我们将求f[i]的递推式f[i]=1+f[1]+f[2]++f[i div 2]作一改进。

1f[2k+1]=1+ f[1]+f[2]++f[(2k+1) div 2]

       =1+ f[1]+f[2]++f[k]

       =1+ f[1]+f[2]++f[(2k) div 2]

       =f[2k]

   即f[2k+1]= f[2k]

2f[2k+2]=1+ f[1]+f[2]++f[k+1]

       =1+ f[1]+f[2]++f[k]+f[k+1]

       =f[2k]+f[k+1]

   即f[2k+2]= f[2k]+f[k+1]

二.几个实例求解过程

f[15]

1)求初值f[1]f[2]

f[1]=1f[2]=2

2)求f[3] f[4]

    f[3]=f[3-1]=f[2]=2

    f[4]=f[4-2]+f[4 div 2]=f[2]+ f[2]=2+2=4

3)求f[5] f[6]

    f[5]=f[5-1]=f[4]=4

    f[6]=f[6-2]+f[6 div 2]=f[4]+ f[3]=4+2=6

4)求f[7] f[8]

    f[7]=f[7-1]=f[6]=6

    f[8]=f[8-2]+f[8 div 2]=f[6]+ f[4]=6+4=10

5f[15]

    f[15]= 1+ f[1]+f[2]+f[3] +f[4] +f[5] +f[6] +f[7] =1+1+2+2+4+4+6+6=26

【算法

1.输入n

2f[1]1

3f[2]2

4s2

5.逐对产生f[2k+1]f[2k+2]的值{f[2k+1]f[2k]f[2k+2]f[2k]+f[k+1]}

6f[n]1+f[1]+f[2]++f[n div 2]

7.输出f[n]

【参考程序

//By LYLtim

var n,i:longword;
    f:array[1..500000]of qword;
    sum:longword;
begin
    assign(input,'count.in');reset(input);
    assign(output,'count.out');rewrite(output);
    read(n);
    close(input);
    sum:=0;
    f[1]:=1;f[2]:=2;
    if n in[1,2]then begin writeln(f[n]); close(output); halt; end;
    for i:=3 to n>>1 do
        begin
            if odd(i) then f[i]:=f[i-1] else f[i]:=f[i-2]+f[i>>1];
            inc(sum,f[i]);
        end;
    writeln(sum+4);
    close(output);
end.

posted on 2011-08-05 10:53  shallyzhang  阅读(287)  评论(0)    收藏  举报