WJMZBMR打osu! / Easy【期望dp】

>Link

luogu P1365


>Description

有一个长度为 n 的仅由 o o o x x x ? ? ?三个字符组成的字符串
设字符串的分数为:其中长度为 a a a 的只包含 o o o 的子串的分数为 a ∗ a a*a aa,整个字符串的分数为极大的这样的子串分数的和。

其中对于 ? ? ?,这个位置 50% 的概率是 o o o, 50% 的概率是 x x x
求这个字符串的分数期望


>解题思路

对于数学期望我们知道, E ( X ) = ∑ x i p i E(X)=∑x_ip_i E(X)=xipi

做的第一道期望dp
所以我们设 f i f_i fi为 s[1~i] 的字符串的期望, g g g为当前’o’子串的长度

对于当位 i i i可知:

  1. s [ i ] = = ′ o ′ : f i = f i − 1 + ( ( l e n + 1 ) 2 − l e n 2 ) = f i − 1 + 2 g + 1 , g + + s[i]=='o':f_i=f_{i-1}+((len+1)^2-len^2)=f_{i-1}+2g+1,g++ s[i]==o:fi=fi1+((len+1)2len2)=fi1+2g+1g++
  2. s [ i ] = = ′ x ′ : f i = f i − 1 , g = 0 s[i]=='x':f_i=f_{i-1},g=0 s[i]==x:fi=fi1g=0
  3. s [ i ] = = ′ ? ′ : s[i]=='?': s[i]==?: 这时答案为前两个的综合 f i = f i − 1 + ( 2 g + 1 + 0 ) / 2 , g = ( g + 1 + 0 ) / 2 f_i=f_{i-1}+(2g+1+0)/2,g=(g+1+0)/2 fi=fi1+(2g+1+0)/2g=(g+1+0)/2

除以二是因为题目描述的概率 状态转移方程不懂的自己手推一下就明白了


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define db double
#define N 300005
using namespace std;

int n;
char s[N];
db f[N], g;

int main()
{
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		s[i] = getchar();
		while (s[i] != 'o' && s[i] != 'x' && s[i] != '?')
		  s[i] = getchar();
	}
	for (int i = 1; i <= n; i++)
	{
		if (s[i] == 'o') f[i] = f[i - 1] + 2 * g + 1, g++;
		else if (s[i] == 'x') f[i] = f[i - 1], g = 0;
		else if (s[i] == '?')
		{
			f[i] = f[i - 1] + g + 0.5;
			g = (g + 1) * 0.5;
		}
	}
	printf ("%.4lf", f[n]);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值