洛谷 P1654 OSU!

洛谷 P1654 OSU!

题目链接:洛谷 P1654 OSU!

算法标签: 期望DP动态规划(DP)

题目

题目描述

osu 是一款群众喜闻乐见的休闲软件。

我们可以把osu的规则简化与改编成以下的样子:

一共有(n)次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,(n)次操作对应为1个长度为n的01串。在这个串中连续的 (X)(1) 可以贡献 (X^3) 的分数,这x个1不能被其他连续的1所包含(也就是极长的一串1,具体见样例解释)

现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五入后保留1位小数。

输入格式

第一行有一个正整数n,表示操作个数。接下去n行每行有一个[0,1]之间的实数,表示每个操作的成功率。

输出格式

只有一个实数,表示答案。答案四舍五入后保留1位小数。

输入输出样例

输入 #1

3 
0.5 
0.5 
0.5

说明/提示

【样例说明】

000分数为0,001分数为1,010分数为1,100分数为1,101分数为2,110分数为8,011分数为8,111分数为27,总和为48,期望为48/8=6.0

N<=100000

题解:

期望(概率)DP

说实话没有直接写出来,也没学过期望DP,(承认自己偷看了一下题解),但是这道题如果耐心推一推式子还是很简单就可以理解的,那么过程如下:

因为题目中讲到连续的1可以贡献(X^3),那么我们来研究(X^3)这个式子,不难发现以下规律:

((x + 1)^3 = (x + 1)^2 imes (x + 1) => x^3 + 3x^2 + 3x + 1)

所以: ((x + 1)^3 - x^3 = 3x^2 + 3x + 1)

这样我们发现了什么,我们可以完全的用关于(x)的多项式来表示((x+1)),同理((x-1))也可以表示(x)。那么对于下一步,我们考虑处理出(x)(x^2)

对于(x)的处理很简单,(x = (x-1) + 1 ~=>~ x_i = x_{i-1} + 1)

那么考虑(x^2),我们可以推出$(x+1)2=x2+2x+1 => x^2_i = x^2_{i-1} + 2 imes x_{i-1}+1 $

那么对于我们所求的(ans)

(ans_i = ans_{i-1} + (3 imes x^2_{i-1}+3 imes x_{i-1}+1))

因为这道题每一步都涉及到了概率(当前数位为1的概率),那么我们就在(x,x^2,ans)的表达式后边都乘上一个当前为概率(p[i]),题目得解。

AC代码

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;

double p[N], x_1[N], x_2[N], ans[N], sum;

int n;

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++ )
	{
		scanf("%lf", &p[i]);
	}
	for (int i = 1; i <= n; i ++ )
	{
		x_1[i] = (x_1[i - 1] + 1) * p[i];
		x_2[i] = (x_2[i - 1] + 2 * x_1[i - 1] + 1) * p[i];
		ans[i] = ans[i - 1] + (3 * x_2[i - 1] + 3 * x_1[i - 1] + 1) * p[i];
	}
	printf("%.1lf
", ans[n]);
	return 0;
}

原文地址:https://www.cnblogs.com/littleseven777/p/11842102.html