[CTSC2016]假面(概率DP)

Posted HocRiser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CTSC2016]假面(概率DP)相关的知识,希望对你有一定的参考价值。

考场上以为CTSC的概率期望题都不可做,连暴力都没写直接爆零。

结果出来发现全场70以上,大部分AC,少于70的好像极少,感觉血亏。

设a[i][j]表示到当前为止第i个人的血量为j的概率(注意特判血量为0的情况)。那么a[i][0]则为这个人的死亡率。

设dp[i]表示当前指定集合中,有i个人存活的概率。

可以发现a[][]和是可以推导出dp[]的,直接DP可以得到70分。同时发现dp[]存在逆变换,所以复杂度就可以通过了。

但是如果写丑了还是会被卡掉,优化方法可以加快读,减少取模次数,以及预处理逆元。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=l; i<=r; i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=210,mod=998244353;
 9 int n,K,Q,op,id,u,v,ans,h[N],s[N],inv[N],dp[N],dp1[N],a[N][N];
10 
11 int rd(){
12     int x=0; bool t=0; char ch=getchar();
13     while (ch<0 || ch>9) t|=(ch==-),ch=getchar();
14     while (ch>=0 && ch<=9) x=x*10+ch-0,ch=getchar();
15     if (t) return -x; else return x;
16 }
17 
18 int ksm(int a,int b){
19     int res;
20     for (res=1; b; a=1ll*a*a%mod,b>>=1)
21         if (b & 1) res=1ll*res*a%mod;
22     return res;
23 }
24 
25 int main(){
26     freopen("faceless.in","r",stdin);
27     freopen("faceless.out","w",stdout);
28     n=rd(); rep(i,1,n) h[i]=rd(),a[i][h[i]]=1;
29     inv[1]=1; rep(i,2,n) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
30     for (Q=rd(); Q--; ){
31         op=rd();
32         if (op==0){
33             id=rd(); u=rd(); v=rd(); int vv=ksm(v,mod-2);
34             a[id][0]=(a[id][0]+1ll*a[id][1]*u%mod*vv%mod)%mod;
35             rep(i,1,h[id])
36                 a[id][i]=(1ll*a[id][i]*(1-1ll*u*vv%mod+mod)+1ll*a[id][i+1]*u%mod*vv)%mod;
37         }else{
38             K=rd();
39             rep(i,1,K) dp[i]=0; dp[0]=1;
40             rep(i,1,K){
41                 s[i]=rd();
42                 for (int j=i; ~j; j--) dp[j]=(1ll*(1-a[s[i]][0]+mod)*dp[j-1]+1ll*a[s[i]][0]*dp[j])%mod;
43             }
44             rep(i,1,K){
45                 ans=0; rep(j,0,K) dp1[j]=0;
46                 if (!a[s[i]][0]) rep(j,0,K-1) ans=(ans+1ll*dp[j+1]*inv[j+1])%mod;
47                 else{
48                     int res=1; rep(j,1,K) if (j!=i) res=1ll*res*a[s[j]][0]%mod; dp1[0]=res;
49                     rep(j,0,K-1){
50                         if (j>0) dp1[j]=1ll*(dp[j]-1ll*(1-a[s[i]][0])*dp1[j-1]%mod+mod)%mod*ksm(a[s[i]][0]%mod,mod-2)%mod;
51                         ans=(ans+1ll*dp1[j]*inv[j+1])%mod;
52                     }
53                 }
54                 ans=1ll*ans*(1-a[s[i]][0]+mod)%mod; printf("%d ",ans);
55             }
56             puts("");
57         }
58     }
59     rep(i,1,n){
60         ans=0;
61         rep(j,1,h[i]) ans=(ans+1ll*j*a[i][j])%mod;
62         printf("%d ",ans);
63     }
64     puts("");
65     return 0;
66 }

 

以上是关于[CTSC2016]假面(概率DP)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 5340: [Ctsc2018]假面

[CTSC2018] 假面

#2552. 「CTSC2018」假面

loj#2552. 「CTSC2018」假面

[CTSC2018]假面

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