数的计算

题目描述

我们要求找出具有下列性质数的个数(包含输入的自然数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;
}
posted @ 2019-07-06 10:22  如梦山河乀  阅读(337)  评论(0编辑  收藏  举报