题目描述
我们要求找出具有下列性质数的个数(包含输入的自然数nn):
先输入一个自然数nn(n \le 1000n≤1000),然后对此自然数按照如下方法进行处理:
-
不作任何处理;
-
在它的左边加上一个自然数,但该自然数不能超过原数的一半;
-
加上数后,继续按此规则进行处理,直到不能再加自然数为止.
输入格式
11个自然数nn(n \le 1000n≤1000)
输出格式
11个整数,表示具有该性质数的个数。
输入输出样例
输入 #1
6
输出 #1
6
说明/提示
满足条件的数为
6,16,26,126,36,136
过不了的递归:
#include<iostream> using namespace std; const int N = 2000; int n = 0; int 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; }
第一种解法:
f[1]=1 f[2]=2=f[1]+1 f[3]=2=f[1]+1 f[4]=4=f[1]+f[2]+1 f[5]=4=f[1]+f[2]+1 #include<iostream> using namespace std; const int N = 2000; int f[N]; int main(){ int n; cin >> n; for(int i = 1;i <= n;i++){ for(int j = 1;j <= i/2;j++){ f[i] += f[j]; } f[i]++; } cout << f[n]; return 0; }
第二种解法:
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; const int N = 2000; int f[N]; int n = 0; int cnt = 1; int main(){ cin >> n; f[0] = f[1] = 1; for(int i = 1;i <= n;i++){ if(!(i%2)){ f[i] = f[i - 1] + f[i/2]; }else{ f[i] = f[i - 1]; } } cout << f[n]; return 0; }
第三种:闫式DP
#include<iostream> using namespace std; const int N = 2000; int f[N]; int n = 0; int cnt = 1; int main(){ cin >> n; f[0] = f[1] = 1; for(int i = 1;i <= n;i++){ f[i] = f[i - 1]; if(!(i%2)){ f[i] = f[i - 1] + f[i/2]; } } cout << f[n]; return 0; }