P1466 [USACO2.2] 集合 Subset Sums
题目描述
对于从
如果
给出
解题思路
- 如果用next_permutation找组合会TLE,所以用DP
- 1<=n<=39 打表出省一 (doge
- 如果1 ~ n 的和是奇数,答案肯定是0
- 定义状态:
f[s]
=将序列分为两部分,每部分的和为s,(计入重复,所以最后cout要/2) - 状态转移方程:
if (j >= i) f[j] += f[j - i];
- 初始化:
f[0] = 1;
带马(暴力+正解+打表)
暴力
#include<bits/stdc++.h> #define int long long using namespace std; int n; int a[40]; int c[40]; signed main() { cin >> n; if ((n * (n + 1) / 2) & 1) { cout << 0 << ","; return 0; } fill(a + 1, a + n + 1, 0); iota(a + 1, a + n + 1, 1); int ans = 0; for (int l = 0; l <= n; l++) { fill(c + 1, c + n + 1, 0); int pos = n; for (int i = 0; i < l; i++) { c[pos--] = 1; } do { int s1 = 0, s2 = 0; for (int i = 1; i <= n; i++) { if (c[i]) { s1 += a[i]; } else { s2 += a[i]; } } if (s1 == s2) { ans++; } } while (next_permutation(c + 1, c + n + 1)); } cout << ans / 2 << ","; return 0; }
正解
#include<bits/stdc++.h> #define int long long using namespace std; int n; int f[1000]; signed main() { cin >> n; int s = n*(n + 1) / 2; if (s & 1) { cout << 0; return 0; } s /= 2; f[0] = 1; for (int i = 1; i <= n; i++) { for (int j = s; j >= 1; j--) { if (j >= i) f[j] += f[j - i]; } } cout << f[s] / 2; return 0; }
打表
#include<bits/stdc++.h> #define int long long using namespace std; int k[] = {0, 0, 0, 1, 1, 0, 0, 4, 7, 0, 0, 35, 62, 0, 0, 361, 657, 0, 0, 4110, 7636, 0, 0, 49910, 93846, 0, 0, 632602, 1199892, 0, 0, 8273610, 15796439, 0, 0, 110826888, 212681976, 0, 0, 1512776590}; signed main() { int n; cin >> n; cout << k[n]; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)