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;
}

浙公网安备 33010602011771号