题解 洛谷P1365 WJMZBMR打osu! / Easy

题解 洛谷P1365 WJMZBMR打osu! / Easy

Date 2019.7.28


题目大意

给出一个长度为n的由o,x,?组成的字符串,对于每连续的a个o,就有a2分。同时,对于任意的?,有50%的概率为o,有50%的概率为x。求解最后期望得到的分数

思路

首先,我们能够看出这道题是一道递推题
那么状态和转移分别时什么呢?

  • 状态

    不难发现,只有最后一个连续的o组成的字符串的长度对我们的递推有影响。于是,我们不妨设一个b数组,记录原字符串到i为止的末尾有几个o。此外,还应有一个记录答案的a数组记录原字符串到i为止期望得到的分数
  • 转移

    显然,我们在转移的时候需要分3种情况。

    1.si=o

    此时,b数组的转移十分简单,即 b i = b i − 1   + 1 b_i=b_{i-1}~+1 bi=bi1 +1而在a数组转移时,我们可以先减去bi-1得的分数,再加上bi得到的分数,即 a i = a i − 1 − b i − 1 × b i − 1 + b i × b i a_i=a_{i-1}-b_{i-1}\times b_{i-1{}}+b_i\times b_i ai=ai1bi1×bi1+bi×bi化简可得 a i = a i − 1 + 2 × b i − 1 + 1 a_i=a_{i-1}+2\times b_{i-1}+1 ai=ai1+2×bi1+1

    2.si=x

    这种情况的转移是最简单的。 b i = 0 , a i = a i − 1 b_i=0,a_i=a_{i-1} bi=0,ai=ai1

    3.si=?

    这是唯一一种涉及到概率和期望这方面知识的情况。此时,转移应为每件事件可得的分数乘以对应事件发生的概率之和。也就是应包含为o时的得分和为x时的得分乘上它们对应的概率。具体写成式子为 b i = ( b i − 1 + 1 ) ÷ 2 + 0 ÷ 2 ; a i = ( a i − 1 + 2 × b i − 1 + 1 ) ÷ 2 + a i − 1 ÷ 2 b_i=(b_{i-1}+1)\div 2+0\div 2;a_i=(a_{i-1}+2\times b_{i-1}+1)\div 2+a_{i-1}\div 2 bi=(bi1+1)÷2+0÷2;ai=(ai1+2×bi1+1)÷2+ai1÷2

下面附上本人的代码

#include
using namespace std;

int n;
char c[300009];
double a[300009],b[300000];

int main ()
{
	scanf("%d",&n);
	scanf("%s",c+1);
	for (int i=1;i<=n;i++)
	{
		if (c[i]=='o')
		{
			b[i]=b[i-1]+1;
			a[i]=a[i-1]+2*b[i-1]+1;
			continue;
		}
		if (c[i]=='x')
		{
			b[i]=0;
			a[i]=a[i-1];
			continue;
		}
		b[i]=(b[i-1]+1+0)/2;
		a[i]=(a[i-1]+2*b[i-1]+1)/2+a[i-1]/2;
	}
	printf("%.4lf\n",a[n]);
	return 0;
}

尾记

这是我踏入OI许多年以来第一次尝试写博客,也是我第一次使用Markdown编辑器,有许多不足的地方,我定会在以后不断努力改正。
同时,这也是我2019年暑假在正睿集训的第一天。今天老师讲了一天的概率与期望,于是我就做了这道题。
希望当我回过头来再看这篇博客的时候,能回忆起我需要的东西

你可能感兴趣的:(题解)