题目描述:
BZOJ4318 题目传送门
长度为n的串,有p[i]的概率为1,1-p[i]的概率为0,求所有极长的连续为1的子串长度的立方之和的期望值。n<=100000
题目分析:
记
f
[
i
]
[
3
]
f[i][3]
f[i][3]表示算到第
i
i
i位前面所有极长的连续为1的子串长度的立方之和的期望,为方便理解,记
f
[
i
−
1
]
[
3
]
=
L
a
s
t
+
N
o
w
f[i-1][3]=Last+Now
f[i−1][3]=Last+Now,
L
a
s
t
Last
Last表示已经完结的期望,
N
o
w
Now
Now表示以
i
i
i结尾的期望,首先让
f
[
i
]
[
3
]
=
L
a
s
t
f[i][3]=Last
f[i][3]=Last,转移状态只有两种:
当前位为0,
f
[
i
]
[
3
]
+
=
N
o
w
∗
(
1
−
p
[
i
]
)
f[i][3]+=Now*(1-p[i])
f[i][3]+=Now∗(1−p[i])
当前为为1,这时候就需要考虑前面连续的1的长度,设加上当前1后末尾连续1的长度为
x
x
x,由
x
3
=
(
x
−
1
)
3
+
3
(
x
−
1
)
2
+
3
(
x
−
1
)
+
1
x^3=(x-1)^3+3(x-1)^2+3(x-1)+1
x3=(x−1)3+3(x−1)2+3(x−1)+1可以得到
E
(
x
3
)
=
E
(
(
x
−
1
)
3
)
+
3
∗
E
(
(
x
−
1
)
2
)
+
3
∗
E
(
x
−
1
)
+
1
E(x^3)=E((x-1)^3)+3*E((x-1)^2)+3*E(x-1)+1
E(x3)=E((x−1)3)+3∗E((x−1)2)+3∗E(x−1)+1记
f
[
i
]
[
2
]
f[i][2]
f[i][2]表示以
i
i
i结尾的连续的1的长度的平方的期望,
f
[
i
]
[
1
]
f[i][1]
f[i][1]表示以
i
i
i结尾的连续的1的长度的期望
可得
f
[
i
]
[
3
]
+
=
(
N
o
w
+
3
f
[
i
−
1
]
[
2
]
+
3
f
[
i
−
1
]
[
1
]
+
1
)
∗
p
[
i
]
f[i][3]+=(Now+3f[i-1][2]+3f[i-1][1]+1)*p[i]
f[i][3]+=(Now+3f[i−1][2]+3f[i−1][1]+1)∗p[i]
合起来就是
f
[
i
]
[
3
]
=
L
a
s
t
+
N
o
w
∗
(
1
−
p
[
i
]
)
+
(
N
o
w
+
3
f
[
i
−
1
]
[
2
]
+
3
f
[
i
−
1
]
[
1
]
+
1
)
∗
p
[
i
]
=
L
a
s
t
+
N
o
w
+
(
3
f
[
i
−
1
]
[
2
]
+
3
f
[
i
−
1
]
[
1
]
+
1
)
∗
p
[
i
]
=
f
[
i
−
1
]
[
3
]
+
(
3
f
[
i
−
1
]
[
2
]
+
3
f
[
i
−
1
]
[
1
]
+
1
)
∗
p
[
i
]
\begin{aligned} f[i][3]&=Last+Now*(1-p[i])+(Now+3f[i-1][2]+3f[i-1][1]+1)*p[i]\\ &=Last+Now+(3f[i-1][2]+3f[i-1][1]+1)*p[i]\\ &=f[i-1][3]+(3f[i-1][2]+3f[i-1][1]+1)*p[i] \end{aligned}
f[i][3]=Last+Now∗(1−p[i])+(Now+3f[i−1][2]+3f[i−1][1]+1)∗p[i]=Last+Now+(3f[i−1][2]+3f[i−1][1]+1)∗p[i]=f[i−1][3]+(3f[i−1][2]+3f[i−1][1]+1)∗p[i]
同理可得
f
[
i
]
[
2
]
=
(
f
[
i
−
1
]
[
2
]
+
2
f
[
i
−
1
]
[
1
]
+
1
)
∗
p
[
i
]
f[i][2]=(f[i-1][2]+2f[i-1][1]+1)*p[i]
f[i][2]=(f[i−1][2]+2f[i−1][1]+1)∗p[i],
f
[
i
]
[
1
]
=
(
f
[
i
−
1
]
[
1
]
+
1
)
∗
p
[
i
]
f[i][1]=(f[i-1][1]+1)*p[i]
f[i][1]=(f[i−1][1]+1)∗p[i]
这道题的拆分以及立方期望转化都很精妙。
Code:
#include<cstdio>
int main()
{
int n;scanf("%d",&n);
double f1=0,f2=0,f3=0,p;
while(n--){
scanf("%lf",&p);
f3=f3+(3*f2+3*f1+1)*p;
f2=(f2+2*f1+1)*p;
f1=(f1+1)*p;
}
printf("%.1f",f3);
}