HBU训练营【动态规划DP】——整数拆分 (15分)

Jack Cheng学完了计算机基础导论,了解到任何一个数都可以用二进制数来表示,爱玩游戏的他忍不住想要玩一个游戏,既然可以用二进制数表示,那么就可以写成若干个二进制数相加,例如: 7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+2、7=1+1+1+1+1+2 ,7=1+1+1+1+1+1+1 总共有六种不同的拆分方式。 再比如:4可以拆分成:4 = 4,4 = 1 + 1 + 1 + 1,4 = 2 + 2,4=1+1+2。 用f(n)表示n的不同拆分的种数,例如f(7)=6. 要求编写程序,读入n(不超过1000000),输出f(n)%1000000000。现在他希望你和他一起来玩这个游戏。

输入格式:
请在这里写输入格式。例如:输入在一行中给出2个绝对值不超过1000的整数A和B。

输出格式:
第一行输入n表示有那个输入,后面每一行输入一个N(1<=N<=1000000)。所有输出只占一行(行末无多余空格)。

输入样例:

1
7

输出样例:

6

这道题一开始把我给看蒙了,它说表示成二进制,还写成若干个二进制数相加的形式,此时有点蒙,再一看给的例子,哪里有0和1,二进制数还有2,还有4?后来查看发现应该是想表达“一个整数总可以拆分为2的幂的和”,也就是用1,2,4,8…这些数表示。这个题我一开始没啥思路,索性列了几个,也参考了(大佬说这个题应该很简单,所以这只能说我菜。。),分奇偶,然后一一列举,就像下面这样,既然分奇偶,就举例相邻项寻找规律

7=1+2+4
7=1+2+2+2
7=1+1+1+4
7=1+1+1+2+2
7=1+1+1+1+1+2
7=1+1+1+1+1+1+1

当n为奇数时,getNum(n) = getNum(n-1); 当n为偶数时,n的拆分可分为包含1和不包含1的情况,前者与n-1的情况相同,后者最小拆分到2,将各项除以2可知与n/2的情况相同。

#include <iostream>
using namespace std;

long a[1000005];

long getNum(long n){
	a[1] = 1;
	for(long i = 2;i<=n;i++){
		if(i%2!=0)
			a[i] = a[i-1];
		else
			a[i] = (a[i-1] + a[i/2])%1000000000;
	}
	return a[n];
}

int main(){
	ios::sync_with_stdio(false);
	long n,m;
	cin >> n;
	while(n--){
		cin >> m;
		printf("%ld%c",getNum(m),n==0?'\n':' ');
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45845039/article/details/108012989