题意
中文题面,难得解释了 题目传送门
分析
- 考虑到概率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
", f3);
}