洛谷 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 \times (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=x^2+2x+1 ~=>~ x^2_i = x^2_{i-1} + 2 \times x_{i-1}+1 $

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

\(ans_i = ans_{i-1} + (3 \times x^2_{i-1}+3 \times 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\n", ans[n]);
    return 0;
}
12-28 01:24