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;
}