一个整数总可以拆分为2的幂的和,例如: 7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+27=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。
输入描述:
每组输入包括一个整数:N(1<=N<=1000000)。
输出描述:
对于每组数据,输出f(n)%1000000000。
示例1
输入
7
输出
6
思路:刚遇到这道题的时候手足无措,背别人一点拨,原来这是一个完全背包的问题,只是换了个皮。背包问题是动态规划的经典问题了。
完全背包就是说有若干个物品,每个物品都可以重复使用无数次,一个容量为N的背包要恰好放入这若干个物品。这道题是问有多少种放法,物品是1,2,4,8, ... 2^p,显然只需要算到2^p <= N的最大的p既可。
因为题目明确给出了数据范围,因此先算出来上面p个数字,然后算出从1~N的所有结果,测试时只需要查表既可。
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <memory>
#include <cstring>
#include <cmath>
#include <map>
#include <iostream>
using namespace std;
const int MAXN = 1000005;
int stuff[100];
int stuffCount;
int dp[MAXN];
int main()
{
stuffCount = 0;
for(int i=1; i < MAXN; i *= 2)
{
stuff[stuffCount++] = i;
}
dp[0] = 1;
for(int i=0; i < stuffCount; i++)
{
for(int j=stuff[i]; j < MAXN; j++)
{
dp[j] = (dp[j]%1000000000 + dp[j-stuff[i]]%1000000000)%1000000000;
}
}
int n;
while(cin>>n)
{
cout << dp[n] << "\n";
}
}