前兩天模擬考考了這道題spa
考試時想到了如何設計狀態,惋惜轉移方程寫錯了。設計
個人想法:設\(dp[i][j]\)表示前i我的借到j元時的指望支出,\(pp[i][j]\)表示前i我的借到j元的機率,\(ans=\sum_{i=L}^{sum}pp[n][i]*(M-dp[n][i])\)(事實上我考場忘記把M乘上對應的機率了)code
但這樣作的問題在於,咱們必須得計算前i我的借到j元的機率是\(100%\)時的指望支出,轉移時會很麻煩(雖然好像也能夠作,不過從此考試時應儘量避免這樣的狀況),因此不如把借到j元的機率也當作指望的一部分乘上去input
最後的方程長這樣:class
\[pp[i][j]=p[i]×pp[i–1][j–m[i]]+(1–p[i])×pp[i–1][j]\]
\[dp[i][j]=(1–p[i])×dp[i–1][j]+p[i]×(dp[i–1][j–m[i]]+pp[i–1][j–m[i]]×m[i]×r[i])\]di
如何理解第二個dp式子呢?co
咱們發現\(dp[i][j]\)表示前\(i\)我的借到\(j\)元時的指望支出*\(pp[i][j]\)display
令\(f[i][j]\)表示前i我的借到j元時的指望支出math
也就是說,\[f[i][j]*pp[i][j]=(1-p[i])*pp[i-1][j]*f[i-1][j]+p[i]*pp[i-1][j-m[i]]*(f[i-1][j-m[i]]+m[i]*r[i])\]
這樣這個看似玄學的式子就能夠解釋的通了return
il int mns(int a,int b){ return a-b<0?a-b+mod:a-b; } il int qpow(int x,int p) { int ans=1; for(; p; p>>=1) { if(p&1) ans=ans*x%mod; x=x*x%mod; } return ans; } signed main() { //freopen("input.txt","r",stdin); read(n),read(L),read(mon); int _100=qpow(100,mod-2); go(i,1,n) read(m[i]),read(r[i]),read(p[i]),sum+=m[i]; go(i,1,n) { r[i]=r[i]*_100%mod; p[i]=p[i]*_100%mod; } pp[0]=1; go(i,1,n){ com(j,sum,m[i]){ pp[j]=(pp[j]*mns(1,p[i])%mod+pp[j-m[i]]*p[i]%mod)%mod; dp[j]=(dp[j]*mns(1,p[i])+(r[i]*m[i]%mod*pp[j-m[i]]%mod+dp[j-m[i]])%mod*p[i])%mod; } com(j,m[i]-1,0){ pp[j]=pp[j]*mns(1,p[i])%mod; dp[j]=dp[j]*mns(1,p[i])%mod; } } int ans=0; go(i,L,sum) ans=(ans+mon*pp[i]%mod-dp[i])%mod; cout<<(ans+mod)%mod; return 0; }