BZOJ 4318 OSU!【概率DP(立方期望)】

题目描述:

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[i1][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(1p[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=(x1)3+3(x1)2+3(x1)+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((x1)3)+3E((x1)2)+3E(x1)+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[i1][2]+3f[i1][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]&amp;=Last+Now*(1-p[i])+(Now+3f[i-1][2]+3f[i-1][1]+1)*p[i]\\ &amp;=Last+Now+(3f[i-1][2]+3f[i-1][1]+1)*p[i]\\ &amp;=f[i-1][3]+(3f[i-1][2]+3f[i-1][1]+1)*p[i] \end{aligned} f[i][3]=Last+Now(1p[i])+(Now+3f[i1][2]+3f[i1][1]+1)p[i]=Last+Now+(3f[i1][2]+3f[i1][1]+1)p[i]=f[i1][3]+(3f[i1][2]+3f[i1][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[i1][2]+2f[i1][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[i1][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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值