2025 CSP-J2 T4 多边形 / polygon 题解

· · 题解

(J 组题解链接:T1、T2、T3、T4、视频题解、游记)

注:本题解非常抽象。

答案与顺序无关,所以先排序。(赛后补题时忘记排序导致 100pts 变成 32pts)

$$ \begin{align} \sum_{j=1}^{i-1}p_j\ge2\\ \sum_{j=1}^{i-1}a_jp_j>a_i\\ \sum_{j=1}^{i-1}[p_j=0\lor p_j=1]=i-1 \end{align} $$ 的个数。[^1]其中: $$ [q]=\left\{\begin{align*} 1&&q\ 为真\\ 0&&q\ 为假\\ \end{align*}\right. $$ 考虑和以及 $a_i\le5000$ 的限制条件,容易想到**背包求方案数**(别问我怎么想到的,赛时就是这么想到的),但是由于 $O(n\sum_{i=1}^na_i)$ 会 TLE,所以赛时痛失 20pts,与 AK 失之交臂。 ~~根据题解~~,我们可以**考虑问题的反方向,即不满足条件的有哪些**。令枚举到 $i$ 时的和为 $j$ 的方案数为 $f_j$(参考上一段),总方案数为 $2^i$,不合法的方案数为 $\sum_{j=1}^{a_{i+1}}f_j$,两者做差即可。这样,需要使用到的 $j$ 的最大值不超过 $\max_{i=1}^na_i$,总时间复杂度为 $O(n\max_{i=1}^na_i)$,可以 AC。 :::success[代码] ``` cpp #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll maxn = 5010, mod = 998244353; ll n, a[maxn], f[maxn], ans; ll qp(ll a, ll b = mod - 2, ll p = mod) { ll ans = 1; while (b) { if (b & 1) { ans = ans * a % p; } a = a * a % p; b >>= 1; } return ans; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n; for (ll i = 1; i <= n; i++) { cin >> a[i]; } sort(a + 1, a + 1 + n); f[0] = 1; for (ll i = 1; i <= n; i++) { for (ll j = maxn - 1; j >= a[i]; j--) { (f[j] += f[j - a[i]]) %= mod; } ll sum = 0; if (i > 1 && i < n) { (ans += qp(2, i)) %= mod; for (ll j = 0; j <= a[i + 1]; j++) { (ans += mod - f[j]) %= mod; } } } cout << ans; return 0; } ``` ::: :::success[视频题解] ![](bilibili:BV1HjkQBQExS) ::: [^1]: 意思是前面 $i-1$ 个数可以选($p_j=1$)或不选($p_j=0$),但是至少选两个,且选的和大于 $a_i$。原条件两边同时减去 $a_i$ 可得。