校内模拟赛 Zbq's Music Challenge
Posted mjtcn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了校内模拟赛 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} 0 & 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; }
以上是关于校内模拟赛 Zbq's Music Challenge的主要内容,如果未能解决你的问题,请参考以下文章