BZOJ-3450 Tyvj1952 Easy(概率dp)
题目描述
有一个长为 \(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;
}
posted on 2020-12-01 19:58 DestinHistoire 阅读(57) 评论(0) 收藏 举报