码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 5340: [Ctsc2018]假面

时间:2018-05-18 23:33:25      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:ace   desc   stdin   ons   eof   esc   memset   geo   ==   

Description

题面

Solution

生命值范围比较小,首先维护每一个人在每个血量的概率,从而算出生存的概率,设为 \(a[i]\)
询问时,只需要考虑生存的人数,可以 \(DP\)
\(g[i][j]\) 表示前 \(i\) 个人活了 \(j\) 个的概率
\(g[i][j]=g[i-1][j-1]*a[i]+g[i-1][j]*(1-a[i])\)

那么考虑每一个人时,我们对其他人做这个 \(DP\) 就行了,可以做 \(O(C*n^3)\)
实际上这是个生成函数 \((a[i]*x+1-a[i])\) ,最终求出的是每一个人的乘积,除掉 \(i\) 这个人的就是我们暴力求出来的 \(DP\) 数组

这样的话是可逆的,我们减去 \((1-a[i])\) 的项,剩下的就都是 \(a[i]\) 的项了,逆推一下即可

#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
    int f;char c;
    for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=205,M=1005,mod=998244353;
inline int qm(int x,int k){
    int sum=1;
    while(k){
        if(k&1)sum=1ll*sum*x%mod;
        x=1ll*x*x%mod;k>>=1;
    }
    return sum;
}
int f[N][M],n,m[N],Q,op,x,p,q,h[N],a[N],tot,c[N],g[N][N],inv[N],res[N];
inline void Modify(){
    gi(x);gi(p);gi(q);
    p=1ll*p*qm(q,mod-2)%mod;q=(1-p+mod)%mod;
    h[0]=(f[x][0]+1ll*f[x][1]*p)%mod;
    for(int i=m[x];i>=1;i--)h[i]=(1ll*f[x][i+1]*p+1ll*f[x][i]*q)%mod;
    for(int i=m[x];i>=0;i--)f[x][i]=h[i],h[i]=0;
}
inline void solve(){
    gi(tot);
    for(int i=1;i<=tot;i++){
        gi(x);
        a[i]=(1-f[x][0]+mod)%mod;
    }
    memset(g,0,sizeof(g));
    g[0][0]=1;
    for(int i=1;i<=tot;i++){
        g[i][0]=g[i-1][0]*(1-a[i]+mod)%mod;
        for(int j=0;j<=i;j++)
            g[i][j]=(1ll*g[i-1][j-1]*a[i]+1ll*g[i-1][j]*(1-a[i]+mod))%mod;
    }
    for(int i=1;i<=tot;i++){
        int I=qm(a[i],mod-2),ans=0;
        for(int j=1;j<=tot;j++)h[j]=g[tot][j];
        for(int j=tot;j>=1;j--){
            ans=(ans+1ll*I*h[j]%mod*inv[j])%mod;
            h[j-1]=(h[j-1]-1ll*h[j]*(1-a[i]+mod)%mod*I)%mod;
            h[j]=0;
        }
        if(ans<0)ans+=mod;
        ans=1ll*ans*a[i]%mod;
        printf("%d ",ans);
    }
    puts("");
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  for(int i=1;i<N;i++)inv[i]=qm(i,mod-2);
  cin>>n;
  for(int i=1;i<=n;i++)gi(m[i]),f[i][m[i]]=1;
  cin>>Q;
  while(Q--){
      gi(op);
      if(op==0)Modify();
      else solve();
  }
  for(int i=1;i<=n;i++){
      int ans=0;
      for(int j=1;j<=m[i];j++)ans=(ans+1ll*f[i][j]*j)%mod;
      printf("%d ",ans);
  }
  return 0;
}

bzoj 5340: [Ctsc2018]假面

标签:ace   desc   stdin   ons   eof   esc   memset   geo   ==   

原文地址:https://www.cnblogs.com/Yuzao/p/9058367.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!