专栏文章

题解:P14360 [CSP-J 2025] 多边形 / polygon(目前仅有本题有民间数据)

P14360题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@minfsqxp
此快照首次捕获于
2025/12/02 01:42
3 个月前
此快照最后确认于
2025/12/02 01:42
3 个月前
查看原文
给出 nn 根小木棍的长度,从中任选若干根,求其拼成多边形的方案数。
1n5000,1V50001 \le n \le 5000, 1 \le V \le 5000,其中 VV 是小木棍长度的最大值。

正难则反。考虑从中任选若干根,不能拼成多边形的方案数。
考虑动态规划。先给小木棍长度升序排序。令 Fi(x)F_i(x) 为只考虑前 ii 根木棍,其长度和恰好为 xx 的方案数。显然 Fi(x)=Fi1(xAi)+Ci(x)F_i(x) = F_{i - 1}(x- A_i) + C_i(x),其中 Ci(x)C_i(x) 表示前 ii 根木棍中长度恰为 xx 的个数。
最终答案即为 2n1n(n2)1in1xAiFi(x)2^n - 1 - n - \binom{n}{2} - \sum\limits_{1 \le i \le n}\sum\limits_{1 \le x \le A_i}F_i(x)
时间复杂度 O(nV)O(nV),空间复杂度 O(n)O(n)
代码CPP
const i64 p = 998244353;
inline i64 mod(i64 x) { return (x % p + p) % p; }
inline i64 qpow(i64 a, i64 b) {
  i64 ret = 1;
  while (b) {
    if (b & 1) ret = mod(ret * a);
    a = mod(a * a);
    b >>= 1;
  }
  return ret;
}
void solve(i32 _) {
  i32 n;
  i64 ans = 0;
  std::cin >> n;
  std::vector<i32> a(n + 2, 0);
  for (i32 i = 1; i <= n; i++) std::cin >> a[i];
  std::sort(a.begin() + 1, a.begin() + n + 1);
  i32 V = a[n];
  std::vector<std::vector<i64>> f(2, std::vector<i64>(V + 2, 0));
  for (i32 i = 1; i <= n; i++) {
    for (i32 j = 1; j <= a[i]; j++) ans = mod(ans + f[1][j]);
    for (i32 j = V - a[i]; j >= 0; j--)
      f[1][j + a[i]] = mod(f[1][j + a[i]] + f[1][j] + f[0][j]);
    f[0][a[i]]++;
  }
  std::cout << mod(qpow(2, n) - 1 - n - mod(n * (n - 1) * qpow(2, p - 2)) - ans)
            << endl;
  return void();
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...