loj#2552. 「CTSC2018」假面

Posted sssy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj#2552. 「CTSC2018」假面相关的知识,希望对你有一定的参考价值。

题目链接

loj#2552. 「CTSC2018」假面

题解

本题严谨的证明了我菜的本质
对于砍人的操作好做找龙哥就好了,blood很少,每次暴力维护一下
对于操作1
(a_i)为第i个人存活的概率,(d_i)为死掉的概率,(g_{i,j})是除i以外活了j个人的概率
那个选中i人的答案就是
[a_i imessum_{j = 0} ^{k - 1}frac{g_{i,j}}{j + 1}]
对于(g_{i,j}) ,设(f_{i,j})表示前(i)个人有(j)个活着的概率,(f_{i,j})可以dp出来
[f_{i,j} = f_{i - 1,j} imes d_i + f_{i - 1,j - 1} imes a_i]
我们可以枚举每次(g_{i,j})的i,然后skip掉,这样的复杂度是(n^3)
然后就可以前缀后缀背包卷积NTT,或者单点删除的分治做法hhhhhhh
其实这个被背包删除物品可以做O(n)
逆着推一下就好了

代码


#include<cstdio> 
#include<cstring> 
#include<algorithm> 
inline int read() { 
    int x = 0,f = 1; 
    char c = getchar(); 
    while(c < '0' || c > '9') c = getchar(); 
    while(c <= '9' && c >= '0') x = x * 10 + c - '0' ,c = getchar(); 
    return x * f; 
} 
const int mod = 998244353; 
const int maxn = 2007; 
long long b[maxn]; 
int n,m ; 
long long p[maxn][maxn]; 
long long inv[maxn]; 
inline int add(int x,int y) { 
    return x + y >= mod ? x + y - mod : x + y; 
} 
inline int fstpow(int x,int k) { 
    int ret = 1; 
    for(;k;k >>= 1,x = 1ll *x * x % mod) 
        if(k & 1) ret = 1ll * ret * x % mod; 
    return ret;  
} 
void solve1(int x,int P) { 
    int rp = 1 + mod - P; 
    for(int i = 0;i <= b[x];++ i) { 
        if(i) p[x][i] = 1ll * p[x][i] * rp % mod; 
        if(i < b[x]) p[x][i] = add(p[x][i] , 1ll * p[x][i + 1] * P % mod) ;  
    } 
} 
int k;
void solve(int k) { 
    static long long f[maxn],g[maxn],h[maxn],t[maxn]; 
    // f存活j个人的概率  
    memset(f,0,sizeof f); 
    f[0] = 1; 
    for(int i = 1;i <= k;++ i) t[i] = read();   
    for(int a,d,i = 1;i <= k;++ i) { 
        a = 1 + mod - p[t[i]][0];
        d = p[t[i]][0];  
        for(int j = i;j >= 0;-- j) 
            f[j] = add((j ? 1ll * f[j - 1] * a % mod : 0) , 1ll * f[j] * d % mod);
    } 
    for(int i = 1;i <= k;++ i) { 
        h[i] = 0; 
        int a = 1 + mod - p[t[i]][0]; 
        if(!p[t[i]][0]) 
            for(int j = 0;j < k;++ j) h[i] = add(h[i],1ll * f[j + 1] * inv[j + 1] % mod); 
        else { 
            int Inv = fstpow(p[t[i]][0],mod - 2); 
            for(int j = 0;j < k;++ j) { 
                g[j] = ((f[j] - (j ? 1ll * g[j - 1] * a % mod : 0) + mod) % mod) * Inv % mod; 
                h[i] = add(h[i],1ll * g[j] * inv[j + 1] % mod); 
            } 
        } 
        h[i] = 1ll * h[i] * a % mod; 
    } 
    for(int i = 1;i <= k;++ i) printf("%d ",h[i]);  
    puts(""); 
} 
main() { 
    //freopen("facel5.in","r",stdin); freopen("w.out","w",stdout); 
    n = read(); 
    for(int i = 1;i <= n;++ i) b[i] = read(), p[i][b[i]] = 1,inv[i] = fstpow(i,mod - 2);
    m = read(); 
    for(int op,i = 1;i <= m;i += 1) { 
        op = read(); 
        if(!op) { 
            int x = read(),u = read(),v = read(); 
            solve1(x,1ll * u * fstpow(v,mod - 2) % mod); 
        } 
        else 
            solve(read());  
    }   
 
    for(int i = 1;i <= n;++ i) { 
        int sum = 0; 
        for(int j = 1;j <= b[i];++ j) 
            sum = add(sum , 1ll * j * p[i][j] % mod) ; 
        printf("%d%c",sum,i != n ? ' ' : '
'); 
    } 
    return 0; 
} 

以上是关于loj#2552. 「CTSC2018」假面的主要内容,如果未能解决你的问题,请参考以下文章

[CTSC2018]假面

[CTSC2018] 假面

[CTSC2018]假面

bzoj 5340: [Ctsc2018]假面

并不对劲的bzoj5340: [Ctsc2018]假面

Loj #2553. 「CTSC2018」暴力写挂