1. 程式人生 > >校內模擬賽 Zbq's Music Challenge

校內模擬賽 Zbq's Music Challenge

線段 cout typedef left space 得到 ali algo ostream

Zbq‘s Music Challenge

題意

  一個長度為n的序列,每個位置可能是1或者0,1的概率是$p_i$。對於一個序列$S$,它的得分是

$$BasicScore=A\times \sum_{i=1}^{n}{S_i} \tag{1}$$

$$ combo(i)=\left\{ \begin{aligned} &S_i & &i=1 \\ &combo(i-1)+1 & &i\neq 1 ~\mathrm{and}~ S_i=1 \\ &combo(i-1)\times t & &\mathrm{otherwise} \end{aligned} \tag{2} \right.$$

$$ComboScore=B\times \sum_{i=1}^{n}{S_i\times combo(i)} \tag{3}$$

$$TotalScore=BasicScore+ComboScore \tag{4}$$

  兩種操作,修改每個位置的概率,詢問一段區間得分的期望,答案對$998244353$取模。

分析

  分成兩部分算,$BasicScore$可以對$p_i$求和得到。

  對於每段區間,$f[i]$設第i位置數字期望是多少,那麽$ComboScore = B \times \sum\limits_{i=l}^{r} p_i \times (f[i-1] + 1) $。

  然後轉移可以寫成矩陣的形式。

  $$ \left[ \begin{matrix} 0 & p_i & p_i \\ 0 & (1 - p_i) \times t + p_i & p_i\\ 0 & 0 & 1 \end{matrix} \right] \times \left[ \begin{matrix} sum\\ f[i - 1]\\ 1 \end{matrix} \right] = \left[ \begin{matrix} sum‘ \\ f[i]\\ 1 \end{matrix} \right] $$

  於是,線段樹維護一下即可。復雜度$O(nlogn \times 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 << "\n";
}
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;
}

校內模擬賽 Zbq's Music Challenge