Yushi难题
时间限制(普通/Java) :
1000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 39 测试通过 : 13
总提交 : 39 测试通过 : 13
比赛描述
有一位著名的数学家,叫Yushi,他提出了一个世纪难题:
给定一个正整数N,由1,2……,N组成的集合
S0={1,2,3,……,N}
对于任意给定的集合,定义集合的和为集合中所有元素的和。
集合S0可以被划分为两个不相交的子集合S1,S2。分别对这两个集合求和,如果两个集合的和相差恰好为K,则记为一种合法的划分方法。考虑N=7,K=0,则合法划分方法一种有4种:{1,2,4,7},{3,5,6};{1,2,5,6},{3,4,7};{1,6,7},{2,3,4,5};{1,3,4,6},{2,5,7}
对于给定的N和K,求出集合的划分方法总数。
输入
仅含一行,两个整数N(1<N<32)和K(0<=K<=100000000)。
输出
仅含有一个数,表示划分集合的合法方案数。
样例输入
7 0
样例输出
4
题目来源
NJU
/*
#include<iostream>
using namespace std;
int main(){
int N, K, i, j, a, sum;
int f[500];
while(scanf("%d%d", &N, &K) == 2){
memset(f,0,sizeof(f));
sum = N*(N+1)/2;
f[1] = f[0] = 1;
if(K >= sum || (sum+K)%2 == 1){
printf("0\n");
}else{
a = (sum+K)/2; // 挑选出若干个数,使得和为 a
for(i=2; i<=N; i++){
for(j=a; j>=i; j--){
f[j] += f[j-i];
}
}
if(K == 0){
f[a]/=2;
}
printf("%d\n",f[a]);
}
}
return 0;
}
*/
/* AC 0MS
#include<iostream>
using namespace std;
#define MAX_N 32
int dp[MAX_N + 1][MAX_N * (MAX_N + 1) / 2];
// dp[i][j] 表示从 1...i 中选取若干个数,使其总和为j的方法数
// dp[n][m] = dp[n - 1][m] + dp[n - 1][m - n]
void init(){
int i, j;
dp[1][0] = dp[1][1] = 1;
for(i = 2; i <= MAX_N; ++i){
for(j = 0; j <= i * (i + 1) / 2; ++j){
dp[i][j] = dp[i - 1][j];
}
for(j = i; j <= i * (i + 1) / 2; ++j){
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - i];
}
}
}
int main(){
int n, k, sum;
init();
while(scanf("%d %d", &n, &k) == 2){
sum = n * (n + 1) / 2;
if(k >= sum || (sum + k) & 1){
printf("0\n");
}else{
printf("%d\n", k ? dp[n][(sum + k) / 2] : dp[n][(sum + k) / 2] / 2);
}
}
}
*/