DestinHistoire

 

BZOJ-3450 Tyvj1952 Easy(概率dp)

题目描述

  有一个长为 \(n(n\leq 3\times 10^5)\) 的字符串,有的字符是 o,有的字符是 x,有的字符是 ?,表示 ox 各有 \(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)    收藏  举报

导航