xy0v0's Blog

Back

做法

容易发现的是:

  • 若给定集合 ​\{p_1,p_2,\cdots,p_n\} ,那么当 ​p_i=p_{i+1}​p_i+p_{i+1}=i 时方案数可翻倍。(开头必然有两种)
  • 若集合合法,则必须满足:
    1. ​p_i < i
    2. ​p_i + p_{i+1} = i​p_i = p_{i+1}

考虑对集合的构造,构造到第 ​i 位时,前缀若有 ​A 个 1, ​B 个 0, 记 ​x=\min (A,B),y=\max(A,B) ,可得到以下:

\begin{array}{c|c|c} \text{条件}&\text{消耗的值}&\text{新状态}\\ \hline x<y,\ \operatorname{cnt}[x]>0 & x &(x,y+1)\\ x<y,\ \operatorname{cnt}[x]=0 & y &(x+1,y)\\ x=y & x &(x,y+1) \end{array}

这里在 ​x<y​cnt[x] 正时必须选择 ​x ,因为如果此时消耗 ​y ,那么新状态为 ​(x+1,y) ,永远不可能选择到 ​x

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
struct mint {
    ...
};
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> cnt(n + 1);
    for (int i = 1; i <= n; i++) {
        int t;
        cin >> t;
        cnt[t]++;
    }
    mint ans = 1;
    int x = 0, y = 0;
    for (int i = 1; i <= n; i++) {
        if (x == y) {
            ans *= 2;
            cnt[x]--;
            y++;
        } else if (cnt[x] > 0) {
            cnt[x]--;
            y++;
        } else {
            cnt[y]--;
            x++;
        }
    }
    cout << ans.x << "\n";
    return 0;
}

补题 | ICPC EC 线上一 D
https://www.xy0v0.top/archives/icpcecol-d
Author xy0v0
Published at 九月 14, 2026