Loading

P1654 OSU! 期望DP

# 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]+3\cdot b[i-1]+3\cdot a[i-1]+1)\cdot p[i]
$$
由于这只是当前位的长度,还需要考虑当前位没有填$1$带来的贡献

因此
$$
f[i] = (f[i-1]+3\cdot b[i-1]+3\cdot a[i-1]+1)\cdot p[i] + f[i-1]\cdot(1-p[i])\\
=f[i-1]+(3\cdot b[i-1]+3\cdot 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]);
} 
posted @ 2021-02-08 20:54  MQFLLY  阅读(62)  评论(0编辑  收藏  举报