题目描述
我们要求找出具有下列性质数的个数(包含输入的自然数nn):
先输入一个自然数nn(n le 1000n≤1000),然后对此自然数按照如下方法进行处理:
不作任何处理;
在它的左边加上一个自然数,但该自然数不能超过原数的一半;
加上数后,继续按此规则进行处理,直到不能再加自然数为止.
输入输出格式
输入格式:
11个自然数nn(n le 1000n≤1000)
输出格式:
11个整数,表示具有该性质数的个数。
输入输出样例
输入样例#1: 复制
6
输出样例#1: 复制
6
说明
满足条件的数为
6,16,26,126,36,136
思路分析:
在打代码之前,我们不妨手动模拟一下
n=0,n=1时,答案显然是1
n=2, ans=2; n=3,ans=2
n=4,ans=4; n=5,ans=4
n=6,ans=6; n=7,ans=6
相信大家也发现了,2n与2n+1(n为非负整数)的答案是一样的 这就是第一个规律
然后我们以n=8为例,手动模拟一下
一共有10组解
8 1 8 2 8 3 8 4 8
1 2 8 1 3 8 1 4 8 2 4 8
1 2 4 8
我打出的东西很像一棵搜索树。。。
当我们把8和8下面的左三棵子树放在一起(即8和下面三列),并将所有的8都改成7,我们能发现,我们得到了n=7时的所有解;
我们再把最右端的子树(即剩下的部分)中的所有8删去,我们得到了n=4时的所有解
就这样,我们可以得到一个递推式,
f(n)=f(n-1) //7=8-1
+f(n/2) //4=8/2
再结合之前发现的规律
就能得到:
n%2==0时
f(n)=f(n-1)+f(n/2)
n%2==1时
f(n)=f(n-1)
然后问题就迎刃而解啦
参考代码:
#include <iostream>
using namespace std;
int main()
{
int n,cn=1,i,f[1001];
f[0]=f[1]=1;
cin>>n;
for(i=2;i<=n;i++)
{
if(i%2==0)
f[i]=f[i-1]+f[i/2];
else
f[i]=f[i-1];
}
cout<<f[n]<<endl;
return 0;
}