BZOJ 4318 OSU! 概率dp

玩OSU!这个游戏,每次操作只有成功与失败,分别记为 0 0 0或者 1 1 1,然后得分为所有的最长 1 1 1的长度的三次方之和。求得分的期望。
f i f_{i} fi表示到第 i i i的期望得分。考虑每次增加对得分的贡献,那么 f i = f i − 1 + p i ( E ( ( x + 1 ) 3 ) − E ( x 3 ) ) f_{i}=f_{i-1}+p_{i}(E((x+1)^3)-E(x^3)) fi=fi1+pi(E((x+1)3)E(x3)),其中 x x x i − 1 i-1 i1状态下的长度。
E ( ( x + 1 ) 3 ) − E ( x 3 ) = 3 E ( x 2 ) + 3 E ( x ) + 1 E((x+1)^3)-E(x^3)=3E(x^2)+3E(x)+1 E((x+1)3)E(x3)=3E(x2)+3E(x)+1
所以考虑维护两个期望分别是 E ( x ) E(x) E(x) E ( x 2 ) E(x^2) E(x2)
E x ( i ) = ( E x ( i − 1 ) + 1 ) ∗ p i Ex(i)=(Ex(i-1)+1)*p_{i} Ex(i)=(Ex(i1)+1)pi
E x 2 ( i ) = ( E x 2 ( i − 1 ) + 2 E x ( i − 1 ) + 1 ) ∗ p i Ex^2(i)=(Ex^2(i-1)+2Ex(i-1)+1)*p_{i} Ex2(i)=(Ex2(i1)+2Ex(i1)+1)pi

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=1e5+7;
double p[N];
double E1[N],E2[N],f[N];
int main() {
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lf",&p[i]);
	for(int i=1;i<=n;i++) {
		E1[i]=(E1[i-1]+1)*p[i];
		E2[i]=(E2[i-1]+2*E1[i-1]+1)*p[i];
		f[i]=f[i-1]+p[i]*(3*E2[i-1]+3*E1[i-1]+1);
	}
	printf("%.1lf\n",f[n]); 
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值