问题描述
我们要求找出具有下列性质数的个数(包含输入的自然数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]作一改进。
(1)f[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]
(2)f[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]=1;f[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;
(5)求f[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;
2.f[1]←1;
3.f[2]←2;
4.s←2;
5.逐对产生f[2k+1]、f[2k+2]的值{f[2k+1]←f[2k]和f[2k+2]←f[2k]+f[k+1]};
6.f[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.