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