/* C时间限制:1 毫秒 | C内存限制:65535 Kb
题目内容:
对于由从1到N(1<=N<=39)这N个连续的整数组成的集合来说,我们有时可以将集合分成两个部分和相同的子集合。
例如,N=3时,可以将集合{1,2,3}分为{1,2}和{3}。此时称有一种方式(即与顺序无关)。
N=7时,共有四种方式可以将集合{1,2,3,...,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。
输出描述
方式数。若不存在这样的拆分,则输出0。
输入样例
7
输出样例
4
*/
//方法一:dfs(会超时)
#include <iostream>
#include <set>
#include <algorithm>
#include <cstring>
using namespace std;
set <string> str;
int n, r_sum;
long long ct = 0;
string visit;
void dfs(int sum, int start){
if(sum > r_sum){
return ;
}
if(sum == r_sum){
// cout << "ct: " << ct << endl;
// cout << visit << "sum = r_sum" << endl;
if(str.count(visit) == 0){
str.insert(visit);
// cout << "init " << visit << endl;
ct++;
}
return ;
}
for(int i = start; i <= n; i++){
if(visit[i - 1] == '0'){
visit[i - 1] = '1';
dfs(sum + i, i);
visit[i - 1] = '0';
}
}
}
int main(){
cin >> n;
for(int i = 0; i < n; i++)
visit += '0';
int sum = 0;
sum = (n + 1) * n / 2;
if(r_sum % 2 == 1){
cout << 0;
return 0;
}
r_sum = sum / 2;
dfs(0, 1);
if(ct >= 2)
cout << ct / 2 << endl;
else
cout << 0 << endl;
return 0;
}
//方法二:dp(类似01背包,当然可以试一下完全用01背包解答)
#include <iostream>
using namespace std;
int dp[10000000];
int main(){
int n, sum = 0;
cin >> n;
for(int i = 1; i <= n; i++)
sum += i;
// cout << sum;
if(sum / 2 * 2 != sum){ //若sum为奇数则直接cout 0
cout << 0 << endl;
return 0;
}
sum /= 2;
dp[0] = 1; //初始化一个
for(int i = 1; i <= n; i++)
for(int j = sum; j >= i; j--)
dp[j] += dp[j - i];
cout << dp[sum] / 2 << endl;
return 0;
}