POJ 2229 Sumsets(dp 递推)

来源:互联网 发布:pc端护眼软件 编辑:程序博客网 时间:2024/05/01 01:23

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;}
0 0
原创粉丝点击