「BZOJ4318」OSU!

Description

osu 是一款群众喜闻乐见的休闲软件。
我们可以把osu的规则简化与改编成以下的样子:
一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1个长度为n的01串。在这个串中连续的 XX11 可以贡献 X3X^3 的分数,这x个1不能被其他连续的1所包含(也就是极长的一串1,具体见样例解释)
现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五入后保留1位小数。

Input

第一行有一个正整数nn,表示操作个数。接下去n行每行有一个[0,1][0,1]之间的实数,表示每个操作的成功率。

Output

只有一个实数,表示答案。答案四舍五入后保留11位小数。

Sample Input

1
2
3
4
3 
0.5
0.5
0.5

Sample Output

1
6.0

HINT

N100000N\leq 100000

Solution

gig_i表示到第ii位的期望连续11的长度。
gi=(1pi)0+pi(gi1+1)g_i=(1-p_i)\cdot 0 + p_i\cdot (g_{i-1}+1)
(x+1)3=x3+2x2+2x+1(x+1)^3=x^3+2x^2+2x+1
fif_i表示到第ii位的期望价值。
fi=fi1+(3gi12+3gi1+1)pif_i=f_{i-1}+(3g_{i-1}^2+3g_{i-1}+1)\cdot p_i
直接维护(3gi12+3gi1+1)(3g_{i-1}^2+3g_{i-1}+1)你就完了。
期望的平方不等于平方的期望。
意味着gi12g_{i-1}^2不等于gi1g_{i-1}期望的平方。
那我们分别维护gig_{i}的期望和gi2g_{i}^2的期望。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<queue>
#include<bitset>
#define mk make_pair
#define fi first
#define nd second
#define pii pair<int,int>
#define pb push_back
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long ll;
inline ll read() {ll x = 0; char ch = getchar(), w = 1;while(ch < '0' || ch > '9') {if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * w;}
void write(ll x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');}
inline void writeln(ll x) {write(x);puts("");}
const int N = 310000;
double f[N], g1[N],g2[N];
int n;
double a[N];
char s[N];
int main() {
n = read();
for(int i = 1; i <= n; ++i) scanf("%lf",&a[i]);
for(int i = 1; i <= n; ++i) {
g1[i] = (g1[i - 1] + 1) * a[i];
g2[i] = (g2[i - 1] + g1[i - 1] * 2 + 1) * a[i];
f[i] = f[i - 1] + (3 * g2[i - 1] + 3 * g1[i - 1] +1) * a[i];
}
printf("%.1f\n",f[n]);
return 0;
}