南邮 OJ 1703 Yushi难题

Yushi难题

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 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);
		}
	}
}
*/


你可能感兴趣的:(ACM,南邮OJ,Yushi难题)