• 题解 CF1450H2 【Multithreading (Hard Version)】


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

    祝大家学习愉快!

  • 相关阅读:
    数据库隔离级别
    Mysql 命令详解
    Mysql 索引
    强化学习(四):蒙特卡洛方法
    强化学习(三):动态编程
    强化学习(二):马尔可夫决策过程
    强化学习(一): 引入
    自然语言处理(五)时下流行的生成模型
    论文选读三 QANet
    皮质学习 HTM 知多少
  • 原文地址:https://www.cnblogs.com/zkyJuruo/p/14152445.html
Copyright © 2020-2023  润新知