版权声明:本人版权意识薄弱,版权声明什么的... https://blog.csdn.net/Ike940067893/article/details/88173606
题意
中文题面,难得解释了 题目传送门
分析
- 考虑到概率
DP,显然可以想到
f(i,j)表示到第
i位末尾有
j个
1的期望值。最后输出
f(n+1,0)即可
- 但
n<=100000
-
x表示连续的
1的个数。所以想想怎么可以得到
x3。
- 有
x3=(x−1)3+3(x−1)2+3(x−1)+1
- 用
E表示期望,记
p[i]表示第
i位选
1的概率,则
E(x3)=( E((x−1)3)+E(3(x−1)2)+E(3(x−1))+E(1) )∗p[i]
- 那么我们假设
f1表示存在于末尾的
x的期望值;
f2表示存在于末尾的
x2的期望值;
f3表示前面的所有
x3的期望值,也就是答案。
- 转移方程式就为:
f3(i)f2(i)f1(i)=f3(i−1)+(3f2(i−1)+3f1(i−1)+1)∗p[i]=(f2(i−1)+2f2(i−1)+1)∗p[i]=(f1(i−1)+1)∗p[i]
- 本来第一个方程式看起来有点奇怪,其实那是合并之后的结果。我们记
Last为
i−1之前的已经完结的
E(x3)的总和,这一部分只是为了为最终输出的答案做贡献才放在
f3里。那么剩下的记为
Now,就是未完结、存在于末尾的
E(x3)。有
Last+Now=f3(i−1)
- 假如这个位置选了
0,那么不会再往后做贡献,但是要把这一部分加到最终答案里面去。这一部分值为
Now∗(1−p[i])
- 否则将会对后面产生贡献,值为
Now∗p[i],其实也就是充当
E(x3)=( E((x−1)3)+E(3(x−1)2)+E(3(x−1))+E(1) )∗p[i]中的
E((x−1)3)
- 所以
f3(i)=Last+Now∗(1−p[i])+(Now+3f2(i−1)+3f1(i−1)+1)∗p[i]=Last+Now∗((1−p[i)]+p[i])+(3f2(i−1)+3f1(i−1)+1)∗p[i]=Last+Now+(3f2(i−1)+3f1(i−1)+1)∗p[i]=f3(i−1)+(3f2(i−1)+3f1(i−1)+1)∗p[i]
- 而且
DP时不用开数组
AC Code(300B)
#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
scanf("%d", &n);
double f1 = 0, f2 = 0, f3 = 0, p;
while(n--) {
scanf("%lf", &p);
f3 += (3*f1 + 3*f2 + 1) * p;
f2 = (f2 + 2*f1 + 1) * p;
f1 = (f1 + 1) * p;
}
printf("%.1f\n", f3);
}