「解题报告」ARC128D Neq Neq

我果然还是适合做这种简单数数,难的我根本不会做,哈哈!

首先我们发现,如果有两个完全相同的相邻的数,那么这两个数中的每一个数都不能够被删除,那么这实际上把整个序列分成了若干段,最后的答案就是每一段的答案的乘积。

现在考虑没有相邻相同的数。观察样例,可以发现形如 abab 的形式,中间的两个数不能够被同时删除。

更进一步,假如整个段形如 ababababab...,那么发现被删除的数的限制为不能够相邻。在一段数中选取若干个不相邻的数,这个简单 DP 就能得出方案数,实际上是斐波那契数。

那么考虑不完全形如这样的数,假设段为 xababababy,那么我们发现,中间这一段我们是可以删除一个前缀和一个后缀的。那么我们考虑将这一段划分成若干个 ababab 段,每相邻两端有一个公共的数。那么我们发现,假如每一段的两端的删除情况固定了,中间的删除情况是容易计算出方案数的。

那么我们就可以设一个简单的 DP,\(f_{i, 0/1}\) 表示考虑到第 \(i\) 段,这一段与上一段的交点是否被删除,直接 DP 即可。初始 \(f_{0,0}=1\),答案为 \(f_{m, 0}\),因为第一个数和最后一个数一定不能被删除。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005, P = 998244353;
int n, a[MAXN];
int f[MAXN];
int g[MAXN][2];
int c(int len, int a, int b) {
    if (a == 0 && b == 0) {
        return f[len - 2];
    } else if (a == 1 && b == 1) {
        int ans = 1 + len - 2;
        for (int i = 0; i <= len - 4; i++) {
            ans = (ans + 1ll * f[i] * (len - 3 - i)) % P;
        }
        return ans;
    } else {
        int ans = 1;
        for (int i = 0; i <= len - 3; i++) {
            ans = (ans + f[i]) % P;
        }
        return ans;
    }
}
int solve(int l, int r) {
    vector<int> t;
    for (int i = l + 1, len = 2; i <= r; i++, len++) {
        if (i == r || a[i - 1] != a[i + 1]) {
            t.push_back(len);
            len = 1;
        }
    }
    int m = t.size();
    g[0][0] = 1;
    for (int i = 1; i <= m; i++) {
        g[i][0] = g[i][1] = 0;
        for (int a = 0; a <= 1; a++) {
            for (int b = 0; b <= 1; b++) {
                g[i][b] = (g[i][b] + 1ll * g[i - 1][a] * c(t[i - 1], a, b)) % P;
            }
        }
    }
    return g[m][0];
}
int main() {
    scanf("%d", &n);
    f[0] = 1, f[1] = 2;
    for (int i = 2; i <= n; i++)
        f[i] = (f[i - 1] + f[i - 2]) % P;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    int l = 1;
    int ans = 1;
    for (int i = 1; i <= n; i++) {
        if (i == n || a[i] == a[i + 1]) {
            ans = 1ll * ans * solve(l, i) % P;
            l = i + 1;
        }
    }
    printf("%d\n", ans);
    return 0;
}
posted @ 2023-03-20 19:24  APJifengc  阅读(18)  评论(0编辑  收藏  举报