Subset Sums
[USACO2.2]集合 Subset Sums
题目描述
对于从 \(1\sim n\) 的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的。举个例子,如果 \(n=3\),对于 \(\{1,2,3\}\) 能划分成两个子集合,每个子集合的所有数字和是相等的:
\(\{3\}\) 和 \(\{1,2\}\) 是唯一一种分法(交换集合位置被认为是同一种划分方案,因此不会增加划分方案总数)
如果 \(n=7\),有四种方法能划分集合 \(\{1,2,3,4,5,6,7 \}\),每一种分法的子集合各数字和是相等的:
\(\{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\),你的程序应该输出划分方案总数。
设\(a[i]\)为元素阶段为\(i\),状态为\(j\),\(f[i][j]\)表示在第\(i\)次抉择,和为\(j\);
状态转移方程:
\[f[i][j] = f[i-1][j] + f[i][j -a[i]]
\]
初始条件为
\[f[0][0] = 0
\]
边界为
\[\huge f_{[n][\frac{sum_n}{2}]}
\]
#include <iostream>
using namespace std;
long long f[1000];
int n;
int main()
{
scanf("%d",&n);
// for(int i = 1 ; i <= n ; i ++ )a[i] = i;
f[0] = 1;
if(n*(n+1)%4 == 0)
{
for(int i = 1 ; i <= n ; i ++ )
for(int j = n*(n+1)/4; j >= i ; j--)
f[j] += f[j - i];
printf("%lld",f[n*(n+1)/4]/2);
}
else printf("0");
return 0;
}
“风雪越是呼啸,雪莲越是绽放”

浙公网安备 33010602011771号