USACO 2.2 Subset Sums

Problem 38: Subset Sums

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:

  • {3} and {1,2}

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:

  • {1,6,7} and {2,3,4,5}
  • {2,5,7} and {1,3,4,6}
  • {3,4,7} and {1,2,5,6}
  • {1,2,4,7} and {3,5,6}

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.

PROGRAM NAME: subset

INPUT FORMAT

The input file contains a single line with a single integer representing N, as above.

SAMPLE INPUT (file subset.in)

7

OUTPUT FORMAT

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.

SAMPLE OUTPUT (file subset.out)

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 ;
}

 

你可能感兴趣的:(USACO)