题目描述
给出一个1-N的集合,将这个集合分成两个,使这两个集合的和相等,问有多少种分法
样例输入
7
样例输出
4
思路
记忆化搜索,设 w i , j w_{i,j} wi,j为到处理第i个数时,距离要求的集合和还差多少,然后直接搜(详见代码
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int n, sum;
ll a[50][1005], ans;
ll dfs(int x, int num)
{
if(a[x][num] >= 0) return a[x][num];
if(!num)
{
a[x][num] = 1;
return 1;
}//距离的没有数字,已经达到目标
if(num < x) {
a[x][num] = 0;
return 0;
} //距离的差已经比现在的数字要小了
if(x > n) {
a[x][num] = 0;
return 0;
}//搜完所有数字了
return a[x][num] = dfs(x + 1, num) + dfs(x + 1, num - x);
}
int main()
{
freopen("subset.in", "r", stdin);
freopen("subset.out", "w", stdout);
memset(a, -1, sizeof(a));
scanf("%lld", &n);
for(int i = 1; i <= n; ++i)
sum += i;
if(sum % 2 == 1) {
printf("0");
return 0;
}
sum = sum / 2;
ans = dfs(1, sum);
printf("%d", ans / 2);
return 0;
}