Farmer John commanded his cows to search for different sets of numbers that sum to a given number. The cows use only numbers that are an integer power of 2. Here are the possible sets of numbers that sum to 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
Help FJ count all possible representations for a given integer N (1 <= N <= 1,000,000).
Input
A single line with a single integer, N.
Output
The number of ways to represent N as the indicated sum. Due to the potential huge size of this number, print only last 9 digits (in base 10 representation).
Sample Input
7
Sample Output
6
题意:给N,N由很多个2的次幂相加得到,求有多少种方案。
思路:
1.第一眼是完全背包,每个物品的价值是1,2,4,8….然后往N里背。
这样的复杂度是O(NlogN)=20*1e6,看题目是2s以为可以过,T了几发。
2.重新思考一下发现有递推的规律。
1=1;
2=1+1;
2=2;
3=1+1+(1);
3=2+(1);
4=1+1+(1+1);
4=2+(1+1);
4=(1+1)*2=2+2;
4=2*2=4;
如果是奇数 那么i的分解式就是在i-1的分解式上+1,所以f[i]=f[i-1]
如果为偶数 i的分解式是在i-2的所有分解式上加1+1 (与奇数i-1在i-2 基础上的结论相合)加上 i/2 的分解式*2 。
两个可以综合起来,就是f[i]=f[i-2]+f[i/2];
//完全背包,HDU可以A 142ms;然而 POJ要T
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define mem(array) memset(array,0 , sizeof array)
using namespace std;
const long long MOD=1e9;
int n;
long long dp[1000005];
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
mem(dp);
dp[0]=1;
for(int i=1;i<=1000000;i=i<<1){
// cout<<i<<endl;
for(int j=i;j<=1000000;j++){
dp[j]=(dp[j-i]+dp[j]) %MOD;
}
}
while(~scanf("%d",&n)){
printf("%lld",dp[n]);
}
return 0;
}
//递推 HDU 14ms POJ也可A
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define mem(array) memset(array,0 , sizeof array)
using namespace std;
const long long MOD=1e9;
int n;
long long dp[1000005];
int main(){
//freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
mem(dp);
dp[0]=dp[1]=1;
for(int i=2;i<=1000000;i++){
// cout<<i<<endl;
dp[i]=(dp[i-2]+dp[i/2]) % MOD ;
}
while(~scanf("%d",&n)){
printf("%lld\n",dp[n]);
}
return 0;
}