[CTSC2016]假面(概率DP)
阿新 • • 發佈:2018-05-08
turn col char name || bsp 優化 style else
考場上以為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(); 13while (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)