BZOJ-3450 Tyvj1952 Easy(概率dp)
阿新 • • 發佈:2020-12-01
題目描述
有一個長為 \(n(n\leq 3\times 10^5)\) 的字串,有的字元是 o
,有的字元是 x
,有的字元是 ?
,表示 o
和 x
各有 \(50\%\) 的可能性,分數是按 \(comb\) 計算的,連續 \(a\) 個 \(comb\) 就有 \(a^2\) 分,\(comb\) 就是極大的連續 o
。
求字串的期望得分。
分析
設 \(dp[i]\) 為以第 \(i\) 位為結尾的連續 o
的期望長度。
若 \(s_i=o,dp[i]=dp[i-1]+1\);若 \(s_i=x,dp[i]=0\);若 \(s_i=?,dp[i]=\frac{dp[i-1]+1}{2}\)
由於 \(E(aX+bY)=aE(X)+bE(Y)\),因此每一段連續 o
是相互獨立、互不影響的,在維護期望長度的同時計算每一位的貢獻:
若 \(s_i=o\),連續 o
的長度從 \(i-1\) 變成 \(i\),貢獻比原來增加了 \((dp[i-1]+1)^2-(dp[i-1])^2=2\times dp[i-1]+1\)。
若 \(s_i=x\),無貢獻。
若 \(s_i=?\),有 \(\frac{1}{2}\) 的概率長度增加至 \(dp[i-1]+1\),貢獻增加了 \(\frac{1}{2}\times ((dp[i-1]+1)^2-(dp[i-1])^2)=dp[i-1]+\frac{1}{2}\)
程式碼
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; double dp[N]; char s[N]; int main() { int n; cin>>n; cin>>(s+1); dp[0]=0; double ans=0; for(int i=1;i<=n;i++) { if(s[i]=='o') { dp[i]=dp[i-1]+1; ans=ans+2*dp[i-1]+1; } if(s[i]=='x') dp[i]=0; if(s[i]=='?') { dp[i]=0.5*(dp[i-1]+1); ans=ans+(dp[i-1]+0.5); } } printf("%.4lf\n",ans); return 0; }