对于从 1 到 N (1 <= N <= 39) 的连续整数集合,划分成两个子集合,且保证每个集合的数字和是相等的。
求有多少种划分方法。
解
DP,背包——
设 f[i][j] 为第 i 个数,前面那一组能合成 j 的方案数。
则 f[i][j] = f[i-1][j] + f[i-1][j-(i-1)]
(这个数放/不放入这一组)
代码
#include<cstdio>
#define L long long
L f[50][1001], n, sum[50];
int main(){
freopen("subset.in","r",stdin);
freopen("subset.out","w",stdout);
scanf("%lld", &n);
for(L i = 1; i <= n; ++i)
sum[i] = sum[i-1] + i;
if(sum[n] % 2 != 0){
printf("0");
fclose(stdin);
fclose(stdout);
return 0;
}
f[0][0] = 1;
for(L i = 0; i < n; ++i)
for(L j = 0; j <= sum[i]; ++j){
f[i+1][j] += f[i][j];
f[i+1][j+i+1] += f[i][j];
}
printf("%lld", f[n][sum[n]>>1] >> 1);
fclose(stdin);
fclose(stdout);
return 0;
}