晓萌希望将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背包问题 进行内存优化。