DestinHistoire

 

BZOJ-4318 OSU!(概率dp)

题目描述

  一共有 \(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]\) 的概率为 \(dp[i]=(dp[i-1]+1)\times p[i]\);有 \(1-p[i]\) 的概率为 \(dp[i]=0\)

  然后考虑计算每一位对答案的贡献:\(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;
}

posted on 2020-12-01 20:32  DestinHistoire  阅读(38)  评论(0编辑  收藏  举报

导航