[bzoj5340]假面

[bzoj5340]假面


全部存概率,第一问直接更新,第二问存 i 个人存活的概率,这个可以用多项式除二项式优化到 n^2

然后复杂度就对了。

  • 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=205;
int m[N],n;
const int mod=998244353;
int g[N][N];
inline int add(int a,int b) {
    a+=b;
    if(a>=mod)a-=mod;
    return a;
}
inline int mul(int a,int b) {
    a=(ll)a*b%mod;
    return a;
}
inline int sub(int a,int b) {
    a-=b;
    if(a<0)a+=mod;
    return a;
}
int INVV[N];
int qpow(int a,int b) {
    int res=1;
    while(b) {
        if(b&1)res=(ll)res*a%mod;
        b>>=1,a=(ll)a*a%mod;
    }
    return res;
}
int inv(int x) {
    return qpow(x,mod-2);
}
inline void init() {
    for(int i=1; i<N; i++)INVV[i]=inv(i);
}
/**&**&**&**/
int psblive(int id) {
    return sub(1,g[id][0]);
}
int psbdead(int id) {
    return g[id][0];
}
int id[N];
int T[N],T2[N];
int f[N];
int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) {
        scanf("%d",&m[i]);
        g[i][m[i]]=1;
    }
    int Q;
    scanf("%d",&Q);
    init();
    while(Q--) {
        int opt;
        scanf("%d",&opt);
        if(opt==0) {
            int id,u,v;
            scanf("%d%d%d",&id,&u,&v);
            int psb1=mul(u,inv(v)), psb2=sub(1,psb1);
            g[id][0]=add(g[id][0],mul(g[id][1],psb1));
            for(int i=1; i<=m[id]; i++) {
                g[id][i]=add(mul(g[id][i+1],psb1),mul(g[id][i],psb2));
            }
        } else {
            int k;
            scanf("%d",&k);
            for(int i=1; i<=k; i++)scanf("%d",&id[i]);
            for(int i=0; i<=k; i++) T[i]=0;
            T[0]=1;
            for(int i=1; i<=k; i++) {
                int pos1=psblive(id[i]),pos2=psbdead(id[i]);
                for(int j=k; j; j--)
                    T[j]=add(mul(T[j],pos2),mul(T[j-1],pos1));
                T[0]=mul(T[0],pos2);
            }
            for(int i=1; i<=k; i++) {
                int pos1=psblive(id[i]),pos0=psbdead(id[i]);
                int inv1=inv(pos1);
                f[k]=0;
                for(int t=k-1; ~t; t--)
                    f[t]=mul(sub(T[t+1],mul(f[t+1],pos0)),inv1);
                int pos11=0;
                for(int t=0; t<=k-1; t++)
                    pos11=add(pos11,mul(f[t],INVV[t+1]));
                pos11=mul(pos11,pos1);
                printf("%d ",pos11);
            }
            puts("");
        }
    }
    int ans=0;
    for(int i=1; i<=n; i++) {
        ans=0;
        for(int j=1; j<=m[i]; j++)
            ans=add(ans,mul(j,g[i][j]));
        printf("%d ",ans);
    }
    puts("");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值