For many sets of consecutive integers from 1 through N (1 <= N <= 39), one can partition the set into two sets whose sums are identical.
For example, if N=3, one can partition the set {1, 2, 3} in one way so that the sums of both subsets are identical:
This counts as a single partitioning (i.e., reversing the order counts as the same partitioning and thus does not increase the count of partitions).
If N=7, there are four ways to partition the set {1, 2, 3, ... 7} so that each partition has the same sum:
Given N, your program should print the number of ways a set containing the integers from 1 through N can be partitioned into two sets whose sums are identical. Print 0 if there are no such ways.
Your program must calculate the answer, not look it up from a table.
The input file contains a single line with a single integer representing N, as above.
7
The output file contains a single line with a single integer that tells how many same-sum partitions can be made from the set {1, 2, ..., N}. The output file should contain 0 if there are no ways to make a same-sum partition.
4
类型:DP
题意:将1~n,n个数分成两组,使其和相等,求一共有多少种分法。改变数字的顺序不会增加分法。
思路:很裸的背包。如果M=n*(n+1)/2是奇数,则没有分法。如果是偶数,背包容量为M/2,dp[k] += dp[k-i],(i=1,2,...,n)计算k的时候为避免重算,
需倒着进行。
/*
ID: superbi1
TASK: subset
LANG: C
*/
#include < stdio.h >
#include < string .h >
int main()
{
unsigned int dp[ 391 ];
int i, j, n, M;
FILE * in = fopen( " subset.in " , " r " );
FILE * out = fopen( " subset.out " , " w " );
fscanf( in , " %d " , & n);
M = n * (n + 1 ) / 2 ;
if (M & 1 ) {
fprintf( out , " 0\n " );
return 0 ;
}
M /= 2 ;
memset(dp, 0 , sizeof (dp));
dp[ 0 ] = 1 ;
for (i = 1 ; i <= n; i ++ ) {
for (j = M - i; j >= 0 ; j -- )
if (dp[j]) {
dp[j + i] += dp[j];
}
}
fprintf( out , " %u\n " , dp[M] / 2 );
return 0 ;
}