时间限制:1秒 空间限制:65536K
题目描述
一个整数总可以拆分为2的幂的和,例如: 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。
输入描述:
每组输入包括一个整数:N(1<=N<=1000000)。
输出描述:
对于每组数据,输出f(n)%1000000000。
示例1
输入
7
输出
6
起初想打表:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MOD 1000000000
long A[5000];
int main() {
long N,res;
memset(A,0,sizeof(A));
for(int i=0; i<=1; i++) {
for(int j=0; j<=2; j++) {
for(int k=0; k<=4; k++) {
for(int l=0; l<=8; l++) {
for(int m=0; m<=16; m++) {
for(int n=0; n<=32; n++) {
res=32*i+16*j+8*k+4*l+2*m+n;
if(res<=32)
A[res]++;
}
}
}
}
}
}
for(int i=1; i<=32; i++) {
printf("%ld %ld\n",i,A[i]) ;
}
return 0;
}
但我竟然没看出来递推公式:
f(2m + 1) = f(2m),
f(2m) = f(2m - 1) + f(m),
初始条件:f(1) = 1。
动态规划如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MOD 1000000000
int dp[1000005];
int a[21];
int main() {
for(int i=1;i<=20;i++){
a[i]=1<<(i-1);
}
int N;
while(scanf("%d",&N)!=EOF){
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<20;i++){
for(int j=a[i];j<=N;j++){
dp[j]+=dp[j-a[i]];
dp[j]%=MOD;
}
}
printf("%d",dp[N]);
}
return 0;
}