CF2077C 题解

CF2077C 题解

妙妙题。

我们可以把 F 看为 \(1\) 的数量减去 \(0\) 的数量。

于是我们想到把 \(1\) 替换为 \(1\),把 \(0\) 替换为 \(-1\)

F 就是 \([l,r]\) 的区间和。

然后我们惊奇地发现一个子序列的分数就是就是 \([\cfrac{\sum_{i=1}^n}{4}]\)

为什么呢?因为均值不等式,左边与右边相加是定值,然后要求相乘的最大值。

于是要求的就是所有子序列的 \([\cfrac{\sum_{i=1}^n}{4}]\) 的和。

把这个恶心的下取整去掉然后直接推推推式子。

于是我们惊人的发现答案就是 \(\cfrac{2^{n-2}(n+sum^2)-2^{n-1}}{4}\),然后就变成了弱智题。

坑:注意特判 \(n=1\) 的情况,这种情况下 \(n-2\) 会变成负数,这种情况应该输出 \(0\)

#include <bits/stdc++.h>
using namespace std;

#define int long long
constexpr int MAXN = 5e5 + 5;
constexpr int MOD = 998244353;
constexpr int inv4 = 748683265;

int n, q, val[MAXN], sum = 0;
string s;

int qpow(int x, int y) {
    int ans = 1;
    while (y) {
        if (y & 1)
            ans = (ans * x) % MOD;
        x = (x * x) % MOD;
        y >>= 1;
    }
    return ans;
}

void work() {
    cin >> n >> q >> s;
    if (n == 1) {
        while (q--) {
            int x;
            cin >> x;
            cout << 0 << endl;
        }
        return;
    }
    sum = 0;
    for (int i = 0; i < n; i++) {
        if (s[i] == '1')
            val[i] = 1;
        else val[i] = -1;
        (sum += val[i] + MOD) %= MOD;
    }
    while (q--) {
        int x;
        cin >> x;
        x--;
        (sum -= val[x] - MOD) %= MOD;
        val[x] = -val[x];
        (sum += val[x] + MOD) %= MOD;
        // cout << sum << endl;
        cout << (qpow(2, n - 2) * (sum * sum % MOD + n) % MOD - qpow(2, n - 1) + MOD) % MOD * inv4 % MOD << endl;
    }
}

int T;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    cin >> T;
    while (T--) work();

    return 0;
}
posted @ 2025-04-19 21:53  LightningCreeper  阅读(23)  评论(0)    收藏  举报