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;
}
原文地址:https://www.cnblogs.com/czhui666/p/13776199.html