【LuoguP1654】OSU! 题解

写在前面

$\text{OSU!}$的嘛。。。$\text{PC}$ 端的音游确实没打过,,,主要 $\text{phigros、Cytus2、MuseDash、Arcaea}$,而且都不是很精通。。。

好了不扯了

传送门

嚯,做到这道题我终于明白期望的线性性有多重要了。。

这道题对于本蒟蒻来说是有点挑战性的,但是实际上是道水题,我就写写这道题我是如何一步一步地明白的吧!

Sourse

首先我们要明确一个点:我们每一次操作 $\text{combo}$ 要将答案累加。

那么要累加甚么呢?$E((x+d)^3) - E(x^3)$。这一次没能接上 $\text{combo}$ 就对已有的答案没有贡献 $E((x+d)^3) - E(x^3) = 0$。

这是为甚么?因为如果我们在此步操作中成功 $\text{combo}$ 了,那么我们就要处理一个连续长度为 $x+1$ 长的三次方,而又因为之前算过连续长度为 $x^3$,所以我们这里把他们相减就是我们在这一步所要累加的。

\[E((x+1)^3) = E(x^3) + 3 \times E(x^2) + 3 \times E(x) + E(1) \]

\[E(x^3) = E(x^3) \]

相减后:$3 \times E(x^2) + 3 \times E(x) + E(1)$ 这就是我们要累加的答案 别忘了乘上概率 $p$ (期望定义)

然后就可以对 $E(x^2)$、$E(x)$ 分别进行维护了

关于为甚么 $f_i = f_{i-1} + p \times (3 \times x2_{i-1} + 3 \times x1_{i-1} + 1)$ 中 $f_{i-1}$ 不用乘 $p$,这个就是刚才我一直解释的"累加"

还不懂的话就要学会借力!问同机房的同学或者老师!他们能给你讲通!(确信)

$\text{Code}$

代码有点丑。。。凑合着看吧~

Code

 #include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#define ll long long
#define mem(x,y) memset(x,y,sizeof(x))
#define re register int
#define iwh printf("我永远爱文虎")
#define ot(x) printf("%d",x)
#define lot(x) printf("%lld",x)
#define MARK printf("~~~")
#define _MARK printf("###")
#define LMARK printf("@@@@@@")
#define SLEEP printf("💤")
#define SLEEPER printf("(~﹃~)~zZ")
#define STUDY printf("📕")
#define _ putchar(' ')
#define endl putchar('\n')
#define char_phi signed
#define N 100005
using namespace std;
int n;
double f[N], x1[N], x2[N];
inline int read(){
    int x = 0; char c;
    while(!isdigit(c = getchar()));
    do{
        x = (x << 3) + (x << 1) + (c & 15);
    }while(isdigit(c = getchar()));
    return x;
}
void work(){
    //唔 OSU的嘛...倒是没打过PC端的音游...
    //这两节课光搞概念和公式了,明天再打这道题吧
    //(x+1)^3 = x^3 + 3*x^2 + 3*x + 1
    //上厕所回来的路上想明白了
    //期望具有线性性,不是吗?
    //所以期望完全可以分开维护
    //E(x+1) = E(x) + E(1)
    //E((x+1)^2) = E(x^2) + 2*E(x) + E(1)
    //E((x+1)^3) = E(x^3) + 3*E(x^2) + 3*E(x) + E(1)
    //然后对于E(x^3),E(x^2),E(x)分开维护就ok了
    //然后E((x+1)^3) 是对答案的贡献!感谢cjhdalao的一语点通
//又有了不明白的地方 不愧是cjh大佬,又点通了!!!
//我爱cjh就像cjh爱姐姐(什)
//x1[i-1],x2[i-1]需要乘p,因为他俩是纯期望推过来的!!!
//f[i-1]不用乘p,是因为f[i-1]是已经算好的答案,而后面那两个才是对答案的贡献
//E((x+1)^3) - E(x^3) = 3*E(x^2) + 3*E(x) + E(1)!!!就是这里!!!
//原来已经算好了,此处再算一个连续串的长度然后和之前的相减才是对答案的贡献
n = read();
double p;
for(re i = 1 ; i &lt;= n ; ++ i){
    scanf("%lf",&amp;p);
    x1[i] = (x1[i-1] + 1) * p;
    x2[i] = (x2[i-1] + 2*x1[i-1] + 1) * p;
    f[i] = f[i-1] + (3*x2[i-1] + 3*x1[i-1] + 1) * p;//终于弄明白了!我要写个blog纪念一下
    // printf("")
}
printf("%.1lf",f[n]);

}
char_phi main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
work();
return 0;
}

posted @ 2022-06-04 21:55  char_phi  阅读(45)  评论(0编辑  收藏  举报