HDU 2709 Sumsets DP

S u m s e t s Sumsets

Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4182 Accepted Submission(s): 1663

Problem Description
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

题解:

就是一个找规律的递推DP题,也可以当做背包问题来做。
我们用DP(x)表示数x用二的幂次相加得到的方法数
①:当n是奇数的时候,它相应的二进制数其实就是n-1的二进制数最后一位的0改成1得到的。因为1是最小的2的幂次,不能再分解了,所以这时候n可以表示成的二的幂次相加的每种方法,就是在n-1表示的二的幂次相加的每种方法的最后再加上一个1,也就是此时DP(n) = DP(n-1)
e.g.
4 = 2+2 = 2+1+1 = 1+1+1+1
5 = 2+2+1 = 2+1+1+1 = 1+1+1+1+1
②:当n是偶数的时候,情况会稍微复杂一点,我们可以把二的幂次相加的各种方法分成两类:
1.相加的各个数中最小的二的幂次是1
2.相加的各个数中最小的二的幂次大于1

对于第一种情况,其实和奇数时的情况是一样的,在n-1的二的幂次相加的表示法后加上一个1就行了
对于第二种情况,要求最小的二的幂次大于1,也就是没有二的幂次等于1,那就可以由n/2的各个幂次相加法的各项乘上2得到
根据这两种分类,可以得到当n为偶数时,DP(n) = DP(n-1) + DP(n/2)
对于这道题,先预处理一下,对于每次输入查询就完事儿了

AC代码:

#include<cstdio>
#include<cstring>
using namespace std;
static const int mod = 1e9;
static const int maxn = 1e6+7;
int dp[maxn],n;
int main(){
    dp[1] = 1;
    for(int i=2;i<=maxn;i++){
        if(i&1) dp[i] = dp[i-1];
        else dp[i] = (dp[i-1] + dp[i/2]) % mod;
    }
    while(scanf("%d",&n)!=EOF){
        printf("%d\n",dp[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43710979/article/details/88588193