# P1654 OSU! 期望DP
## 题意
一个$01$串中每个长度为$X$的全1子串可以贡献$X^3$的分数。
每次有$p_i$的概率在这一位出现$1$,求期望分数
$$
N leq 10^5
$$
## 分析
考虑3次的贡献,先从一次算起
$a[i]$表示到第$i$位的长度为$1$的期望长度是多少
$$
a[i] = (a[i - 1] + 1)cdot p[i]
$$
拓展到二次
$$
b[i] = (b[i - 1] + 2 cdot a[i-1]+1)cdot p[i]
$$
拓展到三次
$$
f[i] = (f[i-1]+3cdot b[i-1]+3cdot a[i-1]+1)cdot p[i]
$$
由于这只是当前位的长度,还需要考虑当前位没有填$1$带来的贡献
因此
$$
f[i] = (f[i-1]+3cdot b[i-1]+3cdot a[i-1]+1)cdot p[i] + f[i-1]cdot(1-p[i])\
=f[i-1]+(3cdot b[i-1]+3cdot a[i-1] + 1)cdot p[i]
$$
维护这三个值即可
## 代码
```c++
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define eps 1e-8
#define equals(a,b) fabs(a-b) < eps
using namespace std;
const int maxn = 1e5 + 5;
int rd(){
int x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
double p[maxn];
double a[maxn],b[maxn],f[maxn];
int main(){
int n = rd();
for(int i = 1;i <= n;i++)
scanf("%lf",&p[i]);
for(int i = 1;i <= n;i++){
a[i] = (a[i - 1] + 1) * p[i];
b[i] = (b[i - 1] + 2 * a[i - 1] + 1) * p[i];
f[i] = f[i - 1] + (3 * b[i - 1] + 3 * a[i - 1] + 1) * p[i];
}
printf("%.1f",f[n]);
}