BZOJ-4318 OSU!(概率dp)
阿新 • • 發佈:2020-12-01
題目描述
一共有 \(n(n\leq 10^5)\) 次操作,每次操作只有成功與失敗之分,成功對應 \(1\),失敗對應 \(0\),\(n\) 次操作對應為一個長度為 \(n\) 的 \(01\) 串。在這個串中連續的 \(x\) 個 \(1\) 可以貢獻 \(x^3\) 的分數,這 \(x\) 個 \(1\) 不能被其他連續的 \(1\) 所包含(也就是極長的一串 \(1\))。
現在給出 \(n\),以及每個操作的成功率,輸出期望分數(四捨五入後保留 \(1\) 位小數)。
分析
設 \(dp[i]\) 為以第 \(i\) 位為結尾的連續 \(1\) 的期望長度,則第 \(i\) 位的期望長度有 \(p[i]\)
然後考慮計算每一位對答案的貢獻:\(E[(x+1)^3-x^3]=E[3x^2+3x+1]=3E(x^2)+3E(x)+1\),注意此處要維護長度的平方的期望,而不是期望長度的平方,因為 長度期望的平方不等於長度平方的期望,即 \(E(x^2)\neq E(x)^2\)。再用 \(dp2[i]\) 記錄以第 \(i\) 位為結尾的連續 \(1\) 的長度的平方的期望,可以藉助 \(dp[i]\) 來轉移,即 \(dp2[i]=(dp2[i-1]+2dp[i-1]+1)\times p[i]\)
程式碼
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; double dp[N],dp2[N],p[N]; char s[N]; int main() { int n; cin>>n; for(int i=1;i<=n;i++) scanf("%lf",&p[i]); dp[0]=0;dp2[0]=0; double ans=0; for(int i=1;i<=n;i++) { dp[i]=(dp[i-1]+1)*p[i]; dp2[i]=(dp2[i-1]+2*dp[i-1]+1)*p[i]; ans=ans+(3*dp2[i-1]+3*dp[i-1]+1)*p[i]; } printf("%.1lf\n",ans); return 0; }