【题解】P1654 OSU!(组合数学,概率,期望)

【题解】P1654 OSU!

post on 2022.5.4:

昨天艾教重新很详细的讲了一遍这道题,之前就感觉这道题并没有完全理解。

昨天艾教讲了之后我才茅塞顿开。这里记录一下艾教的推导过程,一是让我再次捋一遍思路,更加清楚;二是希望我以后见到类似的题目之后,能有所进步,而不是像刚开始一样手足无措。

题目链接

P1654 OSU!

思路分析

解法一

\(P_{i,j}\) 表示现在走到了第 \(i\) 个操作,连续成功了 \(j\) 次。

\(E_i(x)\) 表示现在走到了第 \(i\) 个操作,期望连续成功多少次。

那么根据期望的定义有:

\[E_i(x)=\sum \limits_{j=0}^{\infty} j \times P_{i,j} \]

同理,

\[E_i(x^2)=\sum \limits_{j=0}^{\infty} j^2 \times P_{i,j}\\ E_i(x^3)=\sum \limits_{j=0}^{\infty} j^3 \times P_{i,j} \]

考虑递推式。

假设每次的成功概率是 \(k_i\)

对于第 \(i\) 位,我们有 \(k_i\) 的概率成功,那么假设到第 \(i-1\) 位连续成功了 \(j\) 次,那么第 \(i\) 位上若成功,就连续成功了 \(j+1\) 次,因此同样根据期望的定义我们可以将 \(E_i(x)\)\(P_{i-1,j}\) 表示:

\[\begin{aligned}E_i(x)&=k_i \times \sum \limits_{j=0}^{\infty} (j+1) P_{i-1,j}\\&=k_i \times(\sum\limits_{j=0}^{\infty} j\cdot P_{i-1,j}+\sum \limits_{j=0}^{\infty}P_{i-1,j})\\&=k_i\times(1+E_{i-1}(x))\end{aligned} \]

所以对于二次:

\[\begin{aligned}E_i(x^2)&=k_i \times \sum \limits_{j=0}^{\infty}(j+1)^2 \cdot P_{i-1,j} \\&=k_i \times \sum \limits_{j=0}^{\infty}(j^2+2j+1)\cdot P_{i-1,j} \\&=k_i \times (\sum \limits_{j=0}^{\infty}j^2 \cdot P_{i-1,j} +\sum \limits_{j=0}^{\infty}2j \cdot P_{i-1,j}+\sum \limits_{j=0}^{\infty}P_{i-1,j}) \\&=k_i \times (E_{i-1}(x^2)+2 E_{i-1}(x)+1)\end{aligned} \]

同理,

\[E_i(x^3)=k_i \times (E_{i-1}(x^3)+3E_{i-1}(x^2)+3E_{i-1}x+1) \]

我们可以发现这玩意其实满足二项式定理。

那么其实可以拓展到 \(n\) 次期望(一会再说)。

考虑统计答案。

可以发现:

\[ans_i=(1-k_{i+1})\times E_i(x^3) \]

这个式子如何理解呢?

对于一个答案序列,我们最后统计答案时只计算每一段连续的 1 中最后一个位置的答案

举个例子:当我们最后序列是 0011101101 这个序列时,我们最后答案计算方法是:\(3^3+2^3+1^3=36\)。相当于是序列第 5 个位置为整个答案贡献了 \(2^3\),第 8 个位置贡献了 \(2^3\),第 10 个位置贡献了 \(1^3\)

也就是说,实际上只有每一段的最后一个位置对答案有贡献。而其它位置,可以看做是对答案无贡献的

那么在具体的式子里面如何判断一个位置是不是一段连续的 1 的最后一个位置呢?

显然对于一个位置 \(i\),如果有贡献,那么第 \(i+1\) 个位置一定为 0。

那么就很显然了。根据期望的定义,用第 \(i+1\) 个位置为 0 的概率乘上第 \(i\) 个位置的期望即为 \(ans_i\)

解法二

我们首先从一个例子引入。

假设我们最终的答案序列是 1110110,那么答案显然为 \(3^3+2^3=35\),对于上一种解法,我们是将它看成看成每一段连续的 1 的最后一个位置对答案的贡献求和。

在这里,我们可以换一种思路:将每一段连续的 1 的最后一个位置的贡献分配到这一段包含连续的 1 的所有位置上去。

比如:对于上面这个例子,我们可以看做:第一个位置对答案贡献了 1,第二个位置对答案贡献了 7,第三个位置对答案贡献了 19。

也就是说,对于一段连续的 1 中的第 \(x+1\) 个 1,对答案贡献了 \((x+1)^3-x^3\)。根据期望的定义,每一个是 1 位置 \(i\) 对答案的贡献就是:

\[\begin{aligned}\sum \limits_{j=0}^{\infty}P_{i-1,j}((j+1)^3-j^3) &=\sum \limits_{j=0}^{\infty}P_{i-1,j}(3j^3+3j+1) \\&=\sum \limits_{j=0}^{\infty}3j^3\cdot P_{i-1,j}+\sum \limits_{j=0}^{\infty}3j\cdot P_{i-1,j}+\sum \limits_{j=0}^{\infty}P_{i-1,j} \\&=3E_{i-1}(x^2)+3E_{i-1}(x)+1\end{aligned} \]

所以

\[ans_i=k_i(3E_{i-1}(x^2)+3E_{i-1}(x)+1) \]

拓展

根据一次,二次,三次期望,我们可以拓展到 \(k\) 次期望。

通过解法一中的递推式我们可以发现:

\[E_i(x^k)=k_i \times (E_{i-1}x+1)^k \]

二项式定理解决即可。

代码实现

//luoguP1654
#include<iostream>
#include<cstdio>
#include<iomanip>
using namespace std;
const int maxn=1e5+10;
double p[maxn];
double s1[maxn],s2[maxn],s3[maxn],ans[maxn]; 

inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int main()
{
	int n;
	n=read();
	for(int i=1;i<=n;i++)cin>>p[i];
	for(int i=1;i<=n;i++)
	{
		s1[i]=(s1[i-1]+1)*p[i];
		s2[i]=(s2[i-1]+2*s1[i-1]+1)*p[i];
		s3[i]=(s3[i-1]+3*s2[i-1]+3*s1[i-1]+1)*p[i];
		ans[i]=ans[i-1]+(1-p[i+1])*s3[i];//解法一
		//ans[i]=ans[i-1]+(3*s2[i-1]+3*s1[i-1]+1)*p[i];//解法二
		
	 } 
	cout<<fixed<<setprecision(1)<<ans[n]<<endl;
	return 0;
}

三倍经验

P1365 WJMZBMR打osu! / Easy

CF235B Let's Play Osu!

ARC#157 C

posted @ 2022-05-04 23:09  向日葵Reta  阅读(98)  评论(0编辑  收藏  举报