• 校内模拟赛 Zbq's Music Challenge


    Zbq's Music Challenge

    题意

      一个长度为n的序列,每个位置可能是1或者0,1的概率是$p_i$。对于一个序列$S$,它的得分是

    $$BasicScore=A imes sum_{i=1}^{n}{S_i} ag{1}$$

    $$ combo(i)=left{ egin{aligned} &S_i & &i=1 \ &combo(i-1)+1 & &i eq 1 ~mathrm{and}~ S_i=1 \ &combo(i-1) imes t & &mathrm{otherwise} end{aligned} ag{2} ight.$$

    $$ComboScore=B imes sum_{i=1}^{n}{S_i imes combo(i)} ag{3}$$

    $$TotalScore=BasicScore+ComboScore ag{4}$$

      两种操作,修改每个位置的概率,询问一段区间得分的期望,答案对$998244353$取模。

    分析

      分成两部分算,$BasicScore$可以对$p_i$求和得到。

      对于每段区间,$f[i]$设第i位置数字期望是多少,那么$ComboScore = B imes sumlimits_{i=l}^{r} p_i imes (f[i-1] + 1) $。

      然后转移可以写成矩阵的形式。

      $$ left[ egin{matrix} 1 & p_i & p_i \ 0 & (1 - p_i) imes t + p_i & p_i\ 0 & 0 & 1 end{matrix} ight] imes left[ egin{matrix} sum\ f[i - 1]\ 1 end{matrix} ight] = left[ egin{matrix} sum' \ f[i]\ 1 end{matrix} ight] $$

      于是,线段树维护一下即可。复杂度$O(nlogn imes 3^3)$

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cctype>
    #include<cmath>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int mod = 998244353;
    const int N = 500005;
    int p[N];
    
    int ksm(int a,int b) {
        int res = 1;
        while (b) {
            if (b & 1) res = 1ll * res * a % mod;
            a = 1ll * a * a % mod;
            b >>= 1;
        }
        return res;
    }
    int fen(int a,int b) { return 1ll * a * ksm(b, mod - 2) % mod; }
    
    int sum[N << 2], tt, NowAns, n, A, B;
    struct Mat{ 
        int a[3][3]; 
        Mat() { memset(a, 0, sizeof(a)); }
        void set(int p) {
            a[0][0] = 1;
            a[0][1] = a[0][2] = a[1][2] = p;
            a[1][1] = (1ll * (mod + 1 - p) % mod * tt % mod + p) % mod;
            a[2][2] = 1;
        }
    }T[N << 2];
    Mat operator * (const Mat &A, const Mat &B) {
        Mat C;
        for (int k = 0; k < 3; ++k) 
            for (int i = 0; i < 3; ++i) 
                for (int j = 0; j < 3; ++j) 
                    C.a[i][j] = (C.a[i][j] + 1ll * A.a[i][k] * B.a[k][j] % mod) % mod;
        return C;
    }
    inline void pushup(int rt) {
        T[rt] = T[rt << 1] * T[rt << 1 | 1]; 
        sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % mod;
    }
    void build(int l,int r,int rt) {
        if (l == r) {
            T[rt].set(p[l]); sum[rt] = p[l]; return ;        
        }
        int mid = (l + r) >> 1;
        build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1);
        pushup(rt);
    }
    void update(int l,int r,int rt,int pos) {
        if (l == r) {
            T[rt].set(p[l]); sum[rt] = p[l]; return ;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) update(l, mid, rt << 1, pos);
        else update(mid + 1, r, rt << 1 | 1, pos);
        pushup(rt);
    }
    Mat query(int l,int r,int rt,int L,int R) {
        if (L <= l && r <= R) { NowAns = (NowAns + sum[rt]) % mod; return T[rt]; }
        int mid = (l + r) >> 1;
        if (R <= mid) return query(l, mid, rt << 1, L, R);
        else if (L > mid) return query(mid + 1, r, rt << 1 | 1, L, R);
        else return query(l, mid, rt << 1, L, R) * query(mid + 1, r, rt << 1 | 1, L, R);
    }
    void query() {
        int x = read(), y = read();
        NowAns = 0;
        Mat now = query(1, n, 1, x, y);
        LL ans1 = NowAns, ans2 = now.a[0][2];
        cout << (1ll * ans1 * A % mod + 1ll * ans2 * B % mod) % mod << "
    ";
    }
    int main() {
        read();
        n = read();int Q = read(), ta = read(), tb = read();A = read(), B = read();
        tt = fen(ta, tb);
        for (int i = 1; i <= n; ++i) 
            ta = read(), tb = read(), p[i] = fen(ta, tb);
        build(1, n, 1);
        while (Q --) {
            if (read()) query();
            else {
                int x = read(), ta = read(), tb = read(); 
                p[x] = fen(ta, tb);
                update(1, n, 1, x); 
            }
        }
        return 0;
    }
  • 相关阅读:
    英语语法最终珍藏版笔记-9非谓语动词
    英语语法最终珍藏版笔记-8虚拟语气
    英语语法最终珍藏版笔记-7被动语态
    英语语法最终珍藏版笔记-6“情态动词+have+ done”的含义
    photonView 空指针异常
    What is Photon Server?
    photon server (1)
    Unity3D中的Coroutine及其使用(延时、定时调用函数)
    box head上身旋转问题
    unity-点乘和叉乘的应用
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10651188.html
Copyright © 2020-2023  润新知