(不易)POJ-2229 DP,数的分解

题目大意:给一个N,N可以分解为2的n次幂之和,如7可以这样分解:

1) 1+1+1+1+1+1+1 
2) 1+1+1+1+1+2 
3) 1+1+1+2+2 
4) 1+1+1+4 
5) 1+2+2+2 
6) 1+2+4 

一共6种。      输出N可以分解的种数(结果%1e9)。


题目链接:点击打开链接


分析:

状态:dp[i]表示i的满足条件的种数

然后先来看奇数,对于一个奇数i来说,无论无何怎么分解都会剩下一个1,除了这个1之外其他的组合跟i-1是等价的。

所以 dp[i] = dp[i-1]


然后对于偶数i,我们可以把它的分解方式分成2部分,

①分解的数里不含1,以4为例,则有 2+2 和 4 两种方式,由于不含1且都是2的倍数,我们可以提取一个公因子2变成了(1+1)*2和(2)*2,此时刚好等价于在 i/2 的分解上乘以2,所以此时的种类为dp[i/2]

②分解的数里含1,所以分解的数里至少含有1个1,我们将这个1先挪到一边,剩下的刚好就是 i-1所对应的分解种数即

dp[i-1](或dp[i-2]因为i-1为奇数)

所以 dp[i] = dp[i/2] + dp[i-1]


附上代码:

#include<iostream>
#include<algorithm>
using namespace std;
#define Y 1000000000
int n;
int dp[1000000+5];
int main()
{
	scanf("%d", &n);
	dp[1] = 1;
	for (int i = 2; i <= n; i++)
		if (i % 2) dp[i] = dp[i - 1];
		else dp[i] = (dp[i / 2] + dp[i - 1]) % Y;
	printf("%d\n", dp[n]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值