Problem 38: Subset Sums
Subset Sums
JRM
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:
- {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
題意:
對給出的n,從1到n里挑出一些數(shù)使它們的和等于沒挑過的數(shù)字之和。求滿足這樣條件的組數(shù)。
代碼如下:
/*
LANG: C
TASK: subset
*/
#include<stdio.h>
long long dp[40][400];
int main()
{
freopen("subset.in", "r", stdin);
freopen("subset.out", "w", stdout);
int n, sum, i, j;
scanf("%d", &n);
sum = n * (n + 1);
if ( sum / 2 & 1)//如果所有的和sum/2為奇數(shù)。就沒有符合題意的。
{
printf("0\n");
}
else
{
//dp[i,j]表示在前i個數(shù)里能組成和為j的組數(shù)
sum /= 4;
dp[0][0] = 1;
for (i = 1; i <= sum; i++)
{
dp[0][i] = 0;//因?yàn)橄聵?biāo)最低為0.預(yù)先處理。
}
for (i = 1; i <= n; i++)
{
for (j = 0; j <= sum; j++)
{
//dp[i,j]有兩種組合情況,一種是前i-1個數(shù)里組成和為j的組數(shù)
//一種是前i-1個數(shù)里組成和為j-i的組數(shù),這樣dp[i-1, j-i]加上j本身也是屬于和為j的情況。
if (j < i)//確保j-i>=0
{
dp[i][j] = dp[i-1][j];
}
else
{
dp[i][j] = dp[i-1][j] + dp[i-1][j-i];
}
}
}
printf("%lld\n", dp[n][sum]/2);//因?yàn)槭乔蟪鏊星闆r。所以要除二
}
fclose(stdin);
fclose(stdout);
//system("pause");
return 0;
}