回忆 H1 : (frac{1}{2^cnt} sumlimits_{i = 0, i equiv t pmod 2}^{cnt} |t - i| C_{cnt}^{i})
考虑把 (sumlimits_{i = 0, i equiv t pmod 2}^{cnt} |t - i| C_{cnt}^{i}) 拆开。
[sumlimits_{i = 0, i equiv t pmod 2}^{cnt} |t - i| C_{cnt}^{i}
]
[= sumlimits_{i = 0, i equiv t pmod 2}^{t} (t - i) C_{cnt}^{i} + sumlimits_{i = t + 2, i equiv t pmod 2}^{cnt} (i - t) C_{cnt}^{i}
]
[= t sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt}^i - sumlimits_{i = 0, i equiv t pmod 2}^{t} i C_{cnt}^i + sumlimits_{i = t + 2, i equiv t pmod 2}^{cnt} i C_{cnt}^{i} - tsumlimits_{i = t + 2, i equiv t pmod 2}^{cnt} C_{cnt}^{i}
]
因为 (i C_{cnt}^{i} = cnt C_{cnt - 1}^{i - 1})
[2 t sumlimits_{i = 0, i equiv tpmod 2}^{t} C_{cnt}^i - 2 cnt sumlimits_{i = 0, i equiv tpmod 2}^{t} C_{cnt - 1}^{i - 1} + cnt sumlimits_{i = 0, i equiv tpmod 2}^{cnt} C_{cnt - 1}^{i - 1} - tsumlimits_{i = 0, i equiv tpmod 2}^{cnt} C_{cnt}^{i}
]
因此我们只要能快速计算 (sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt}^i) 就可以快速得到答案。
[sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt}^i
]
[sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt - 1}^{i - 1} + C_{cnt - 1}^{i}
]
[sumlimits_{i = 0}^{t} C_{cnt - 1}^{i}
]
这个东西在 (cnt) 改变和在 (t) 改变时都可以快速计算。
主要是利用 (C_{x}^{i} = C_{x - 1}^i + C_{x - 1}^{i - 1})
注意 (t) 可能为负数。。。蒟蒻因为这个调了一个晚上。。。
#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++)
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define ull unsigned long long
#define db long double
#define pii pair<int, int>
#define mkp make_pair
using namespace std;
const int N = 2e5 + 7;
const int mod = 998244353;
const int inv2 = (mod + 1) / 2;
int qpow(int x, int y) {
int res = 1;
for(; y; x = 1ll * x * x % mod, y >>= 1) if(y & 1) res = 1ll * res * x % mod;
return res;
}
int ny(int x) { return qpow(x, mod - 2); }
int jc[N], njc[N];
int C(int x, int y) { if(x < 0 || y < 0 || x < y) return 0; return 1ll * jc[x] * njc[y] % mod * njc[x - y] % mod; }
struct WORKER {
int cnt, t, ans = 1;
// 维护 sumlimits_{i = 0}^{t} C_{cnt}^{i}
void cntup() { ans = (ans << 1) % mod, (ans += mod - C(cnt, t)) %= mod, ++cnt; if(cnt == 0) ans = (t >= 0); }
void cntdown() { if(cnt == 0) ans = 0; --cnt, (ans += C(cnt, t)) %= mod, ans = 1ll * ans * inv2 % mod; }
void tup() { (ans += C(cnt, t + 1)) %= mod, ++ t; }
void tdown() { (ans += mod - C(cnt, t)) %= mod, -- t; }
} a, b, c, d;
int n, m, t, cnt, ans;
char s[N];
int getans() {
int res = 0;
if(cnt == 1) {
L(i, 0, cnt) if((t + i) % 2 == 0) (res += 1ll * abs(t - i) * C(cnt, i) % mod) %= mod;
res = 1ll * res * inv2 % mod;
return res;
}
(res += 2ll * (t + mod) % mod * a.ans % mod) %= mod;
(res += mod - 2ll * cnt * b.ans % mod) %= mod;
(res += 1ll * cnt * c.ans % mod) %= mod;
(res += mod - 1ll * (t + mod) % mod * d.ans % mod) %= mod;
res = 1ll * res * qpow(inv2, cnt) % mod;
return res;
}
void tup() { a.tup(), b.tup(), t++; }
void tdown() { a.tdown(), b.tdown(), t--; }
void cntup() { a.cntup(), b.cntup(), c.cntup(), d.cntup(), c.tup(), d.tup(), cnt++; }
void cntdown() { a.cntdown(), b.cntdown(), c.cntdown(), d.cntdown(), c.tdown(), d.tdown(), cnt--; }
int main() {
scanf("%d%d", &n, &m);
scanf("%s", s + 1);
jc[0] = njc[0] = 1;
L(i, 1, n) jc[i] = 1ll * jc[i - 1] * i % mod, njc[i] = ny(jc[i]);
a.cntdown(), b.cntdown(), c.cntdown(), d.cntdown(), b.cntdown(), c.cntdown(), b.tdown(), c.tdown();
L(i, 1, n) {
if(s[i] == 'b') {
if(i % 2) tdown();
else tup();
}
else if(s[i] == '?') {
cntup();
if(i % 2 == 0) tup();
}
}
printf("%d
", getans());
while(m--) {
int x; char opt[5]; scanf("%d%s", &x, opt + 1);
if(opt[1] == 'b') {
if(x % 2) tdown();
else tup();
}
else if(opt[1] == '?') {
cntup();
if(x % 2 == 0) tup();
}
if(s[x] == 'b') {
if(x % 2) tup();
else tdown();
}
else if(s[x] == '?') {
cntdown();
if(x % 2 == 0) tdown();
}
s[x] = opt[1];
printf("%d
", getans());
}
return 0;
}
祝大家学习愉快!