[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)的主要内容,如果未能解决你的问题,请参考以下文章