P1654 OSU! 期望概率DP

P1654 OSU!

题目链接

​ 期望概率DP。

​ 设\(x\)为连续1的个数,那么多一个1他增加的贡献就是:\((x + 1) ^ 3 - x ^ 3 = 3 * x ^ 2 + 3 * x + 1\)

​ 所以我们需要维护\(x\)的期望和\(x ^ 2\)的期望。

\(x\)的期望:\(x[i] = (x[i - 1] + 1) * p[i]\)

\(x ^ 2\)的期望:\(x2[i] = (x2[i - 1] + 2 * x[i - 1] + 1) * p[i]\)

​ 答案的期望:\(x3[i] = x3[i - 1] + (3 * x2[i - 1] + 3 * x[i - 1] + 1) * p[i]\)
有一个地方困扰了我好久,就是为什么算x, x2的时候要把x[i - 1], x2[i - 1]括到括号里,而x3就不用。
首先要清楚x,x2数组的定义是结尾为i的连续的1的长度,结尾为i的连续的1的长度的平方。而x3数组的定义是最终答案的期望,并不是结尾为i的连续的1的长度的三次方。
所以对于x3:\(ans = \displaystyle \sum_{i=1}^{n} E[i]\),对于x,x2就是i-1的期望加上新的贡献再乘上概率。
或者也可以这么写:\(x3[i] = (x3[i - 1] + 3 * x2[i - 1] + 3 * x[i - 1] + 1) * p[i] + x3[i - 1] * (1 - p[i])\)

#include <bits/stdc++.h>
    
using namespace std;
    
inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}
    

const int N = 1e5 + 5;
int n;
double a[N], x[N], x_2[N], x_3[N];

int main() {
    
    n = read();
    for(int i = 1;i <= n; i++) scanf("%lf", &a[i]);
    for(int i = 1;i <= n; i++) {    
        x[i] = (x[i - 1] + 1) * a[i];
        x_2[i] = (x_2[i - 1] + 2 * x[i - 1] + 1) * a[i];
        x_3[i] = x_3[i - 1] + (3 * x_2[i - 1] + 3 * x[i - 1] + 1) * a[i];
    }
    printf("%.15lf", x_3[n]);

    return 0;
}
posted @ 2020-10-07 06:20  C锥  阅读(95)  评论(0编辑  收藏  举报