等和的分隔子集

晓萌希望将1到N的连续整数组成的集合划分成两个子集合,且保证每个集合的数字和是相等。例如,对于N=3,对应的集合{1,2,3}能被划分成{3} 和 {1,2}两个子集合.

这两个子集合中元素分别的和是相等的。

对于N=3,我们只有一种划分方法,而对于N=7时,我们将有4种划分的方案。

输入包括一行,仅一个整数,表示N的值(1≤N≤39)。

输出包括一行,仅一个整数,晓萌可以划分对应N的集合的方案的个数。当没发划分时,输出0。

样例输入

7

样例输出

4

水dp 啊

dp[i][j]表示前i个数和为j的数量

那么 dp[i][j]=dp[i-1][j]+dp[i-1][j-i]

那么 显然答案就是 dp[n][sum/2]

/* ***********************************************
Author        :guanjun
Created Time  :2016/10/9 14:28:29
File Name     :jisuanke28.cpp
************************************************ */
#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define mod 90001
#define INF 0x3f3f3f3f
#define maxn 10010
#define cle(a) memset(a,0,sizeof(a))
const ull inf = 1LL << 61;
const double eps=1e-5;
using namespace std;
priority_queue<int,vector<int>,greater<int> >pq;
struct Node{
    int x,y;
};
struct cmp{
    bool operator()(Node a,Node b){
        if(a.x==b.x) return a.y> b.y;
        return a.x>b.x;
    }
};

bool cmp(int a,int b){
    return a>b;
}
int dp[50][1000];
int main()
{
    #ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    #endif
    //freopen("out.txt","w",stdout);
    int n;
    while(cin>>n){
        int sum=(n+1)*n/2;
        if(sum&1){
            puts("0");continue;
        }
        else{
            dp[0][0]=1;
            for(int i=1;i<=n;i++){
                 for(int j=1;j<=sum;j++){
                     if(j>=i)dp[i][j]=dp[i-1][j]+dp[i-1][j-i];
                     else dp[i][j]=dp[i-1][j];
                 }
            }
            cout<<dp[n][sum/2]<<endl;
        }
    }
    return 0;
}

可以类bi背包问题 进行内存优化。

posted on 2016-10-09 14:46  Beserious  阅读(625)  评论(0)    收藏  举报