poj 2229(DP)

Sumsets
Time Limit: 2000MS   Memory Limit: 200000K
Total Submissions: 22646   Accepted: 8681

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

题目大意:让你求一个整型N,能够被2的整数幂所组成的情况个数,最终的结果要mod1e9;

先说说我的思路,由于刚看完dp之划分数,本以为是划分数,结果看完大牛的题解后发现是完全背包,但是我感觉用递推来做更好想(哪个都不好想光是递推就看了很长时间快哭了),下面讲一下思路:

当n时奇数时,dp[n]=dp[n-1],拿样例7来说,无非就是在6的每种情况下+1呗(这比是偶数的情况好想到,也好理解,至少我认为是这样的),奇数肯定每一种组合数中都会有1的,从下面来看dp[6]的每一种组合情况+1的结果是不变的。

1) 1+1+1+1+1+1           +1;

 2) 1+1+1+1+2              +1 ;

3) 1+1+2+2                   +1;
4) 1+1+4                      +1;
5) 2+2+2                       +1;

6) 2+4                            +1;

即dp[i]=dp[i-1]

当n是偶数的情况 我拿n=6来说,以下是6的组合情况:

111111                11112             1122             114      222           24

共有6种,我们可以把它分为有1的情况和没有1的情况   把有1 的情况拿出减去分别-1 得到11111     1112     122    14这是dp[5]的结果  ,接下来看剩下没有1 的组合数222 和24将它们都除以2得到111 12两种情况(这是dp[2]的情况),无非就是dp[2]每一项*2的结果,并且结果不变

即dp[i]=dp[i-1]+dp[i/2];

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXN 40005
#define mem(a,b) memset(a,b,sizeof(a));//算是宏定义的应用吧
int dp[1000004];
int N=1e9;
int main()
{
    mem(dp,0);
    int n;
    cin>>n;
    dp[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(i&1==1)//利用位运算,奇数的二机制的最后一位都是1
            dp[i]=dp[i-1];
        else
            dp[i]=(dp[i-1]+dp[i>>1])%N;//dp[i>>1]是/2的意思,反之i<<1左移1位是*2;
    }
    cout<<dp[n]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/c___c18/article/details/80761268