/* 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; }