Description |
对于从1到N (1 <= N <= 39) 的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的。举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,每个子集合的所有数字和是相等的: {3} 和 {1,2} 这是唯一一种分法(交换集合位置被认为是同一种划分方案,因此不会增加划分方案总数) 如果N=7,有四种方法能划分集合{1,2,3,4,5,6,7},每一种分法的子集合各数字和是相等的: {1,6,7} 和 {2,3,4,5} {注 1+6+7=2+3+4+5} {2,5,7} 和 {1,3,4,6} {3,4,7} 和 {1,2,5,6} {1,2,4,7} 和 {3,5,6} 给出N,你的程序应该输出划分方案总数,如果不存在这样的划分方案,则输出0。 |
Input |
有多组测试数据。 对于每组测试数据,输入一个整数n。 |
Output |
对于每组测试数据,输出划分方案总数,如果不存在则输出0。 |
Sample Input |
7 |
Sample Output |
4 |
思路:先鄙视一下自己,简单的01背包问题,比赛的时候硬是没有ac;
dp[i][j]表示前i个数组成和为j的方法数;
代码如下;
View Code
#include<stdio.h> #include<string.h> long long dp[50][500]; int main() { int i, j, n, sum; while(scanf("%d", &n)!=EOF) { sum=0; memset(dp, 0, sizeof(dp)); for(i=1; i<=n; i++) sum+=i; if(sum%2==1) { printf("0\n"); continue; } dp[0][0]=1; for(i=1; i<=n; i++) { for(j=0; j<=sum/2; j++) { if(j>=i) dp[i][j]+=dp[i-1][j-i]; dp[i][j]+=dp[i-1][j]; } } printf("%lld\n", dp[n][sum/2]/2); } }