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;
    
}
posted @ 2022-07-14 18:07  Erfu  阅读(86)  评论(0)    收藏  举报