题目描述
我们要求找出具有下列性质数的个数(包含输入的自然数nnn):
先输入一个自然数nnn(n≤1000),然后对此自然数按照如下方法进行处理:
不作任何处理;
在它的左边加上一个自然数,但该自然数不能超过原数的一半;
加上数后,继续按此规则进行处理,直到不能再加自然数为止.
输入格式:
1个自然数n(n≤1000n)
输出格式:
1个整数,表示具有该性质数的个数。
输入输出样例
输入样例#1:
6
输出样例#1:
6
满足条件的数为
6,16,26,126,36,136
①利用递归的方法
#include<cstdio>
using namespace std;
int n,cnt=1;
void func(int x)
{
for(int i=1;i<=x/2;i++)
{
cnt++;
func(i);
}
}
int main()
{
cin>>n;
func(n);
cout<<cnt;
}
此法很容易算出答案,但是对于较大的数据会超时。
②利用递推(DP)的方法
观察规律知道 :
f[i]=f[i-1]+f[i/2]
i为偶数时
故有以下做法:
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
int a,f[1001]={0};//创建数组f及时保存对应数的值 防止超时
cin>>a;
f[0]=f[1]=1;
f[2]=2;
a=a/2*2;//因为奇数项与比他小的那一项值相同
for(int i=2;i<=a;i++)
{
if(i%2==0)
f[i]=f[i-1]+f[i/2];
else
f[i]=f[i-1];
}
cout<<f[a];
}
③打表法
先利用代码打印出1~1000对应的所有解,再利用查找的方式过虚拟机
下面是打表代码
#include <cstdio>
#include <iostream>
using namespace std;
long long dfs(int x) //深搜
{
if(x==1) return 1;
long long tot=1; //加上自身,所以初始化是 1
for(int i=1;i<=x/2;i++) //列举
tot+=dfs(i);
return tot;
}
int main()
{
cout<<"a[1001]={"; //便于直接复制
for(int i=1;i<=1000;i++) //枚举所有数
{
cout<<dfs(i)<<",";
}
cout<<"}";
}
打表后即可写出AC代码(由于代码过长 此处就不放了)