期望概率二讲

这一讲很难很难很难。

讲题人:吴立俊

考虑期望的两个重要性质:

\[E(x)=\sum _i P(x=i) \]

这个公式描述了期望和概率的关系。

\[E(x+y)=E(x)+E(y),E(kX)=kE(X) \]

这个公式描述了期望的线性性。

那么下面要做一点逆天的事情。

B

\(n\) 种不同的邮票,皮皮想收集所有种类的邮票。唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是 \(n\) 种邮票中的哪一种是等概率的,概率均为 \(1/n\)。但是由于凡凡也很喜欢邮票,所以皮皮购买第 \(k\) 次邮票需要支付 \(k\) 元钱。

现在皮皮手中没有邮票,皮皮想知道自己得到所有种类的邮票需要花费的钱数目的期望。

sol

老师给的题解错误过多,所以我改了一改。

先考虑怎样去计算答案,显然答案是 \(E(\dfrac{m(m+1)}{2})\),利用期望的线性性,得到 \(ans=\dfrac{1}{2}E(m^2)+E(m).\)

\(E(m)\) 也就是期望步数,可以得到 \(f(x)\) 是已经有 \(x\) 张之后步数的期望。 \(f(i)=1+\dfrac{i}{n} f(i)+\dfrac{n-i}{n} f(i+1).\)

考虑 \(E(m^2).\)\(g(x)\) 为有 \(x\) 张邮票时拿满 \(x\) 张的步数平方期望。

\(p_1(i),p_2(i)\) 分别是 \(x,x+1\) 张时,用 \(i\) 步拿完的概率。显然可以得到以下:

\[f(x)=\sum_i ip_1(i)=E(p_1(i)) \]

\[f(x+1)=\sum_iip_2(i) \]

\[g(x)=\sum_{i}i^2p_1(i),g(x+1)=\sum_ii^2p_2(i) \]

\[p_1(i)=\sum_{j<i}p_2(j)\left(\dfrac{x}{n}\right)^{i-j-1}\times \dfrac{n-x}{n} \]

最后一个式子其实有 \(0,1\) 两种决策,这之中的 \(0\) 决策省略。

为什么呢?

首先为了使 \(p_1,p_2\) 关联,你要先取 \(i-j-1\) 次旧的不造成任何贡献,还要取到 \(1\) 张新的也就是 \(\dfrac{n-x}{n}.\) 原因显然。

我们慢慢化简 \(g\) 并且调换 \(i,j\) 的位置可以得到以下:

\[g(x)=\sum _i i^2 \sum_{j<i}p_2(j)\left(\dfrac{x}{n}\right)^{i-j-1}\times\dfrac{n-x}{n} \]

再一次化简,

\[g(x)=\dfrac{n-x}{x}\sum_ip_2(i)\sum_{j>i}j^2\left(\dfrac{x}{n}\right)^{j-i} \]

然后带入 \(p_1(i)\) 的式子发现 \(f(x)\) 会长成下面的样子:

\[f(x)=\dfrac{n-x}{x}\sum_ip_2(i)\sum_{j>i}j\left(\dfrac{x}{n}\right)^{i-j} \]

转而在 \(g\) 式子中枚举 \(j-i\),可以获得如下:

\[g(x)=\dfrac{n-x}{n}\sum_ip_2(i)\sum_{d=1}^{+\infty}(i+d)\left(\dfrac{x}{n}\right)^d \]

考虑利用下面的式子计算 \(p_2\) 的系数:

\[\sum_{i=1}^{+\infty}(a+b)^2A^i=\sum_{i=1}^{+\infty}a^2A^i+\sum_{i=1}^{+\infty}2abA^i+\sum_{i=1}^{+\infty}b^2A^i \]

用这个式子和无穷递缩等比数列求和公式并且返回生成函数可以得到如下:

\[g(x)=g(x+1)+f(x+1)+\dfrac{n+x}{n-x}f(x) \]

注意到 \(f(x),g(x)\) 分别与 \(f(x+1),g(x+1)\) 有关,所以可以将程序倒序枚举。

程式
#include <bits/stdc++.h>
#define ll long long
#define db long double
using namespace std;
const int N=1e5+10;
db f[N],g[N];
int n;
int main(){
	cin>>n;
	for(int i=n-1;i>=0;--i) f[i]=f[i+1]+1.0*n/(n-i);
	for(int i=n-1;i>=0;--i) g[i]=g[i+1]+f[i+1]+1.0*(n+i)/(n-i)*f[i];
	printf("%.2Lf",(f[0]+g[0])/2 );
}

D

她长大以后创业了,开了一个公司。 但是管理公司是一个很累人的活,员工们经常背着可怜偷懒,可怜需要时不时对办公室进行检查。

可怜公司有 \(n\) 个办公室,办公室编号是 \(l\)\(l+n-1\) ,可怜会事先制定一个顺序,按照这个顺序依次检查办公室。一开始的时候,所有办公室的员工都在偷懒,当她检查完编号是 \(i\) 的办公室时候,这个办公室的员工会认真工作,并且这个办公室的员工通知所有办公室编号是 \(i\) 的倍数的办公室,通知他们老板来了,让他们认真工作。因此,可怜检查完第 \(i\) 个办公室的时候,所有编号是 \(i\) 的倍数(包括 \(i\) )的办公室的员工会认真工作。

可怜发现了员工们通风报信的行为,她发现,对于每种不同的顺序 \(p\) ,都存在一个最小的 \(t(p)\) ,使得可怜按照这个顺序检查完前 \(t(p)\) 个办公室之后,所有的办公室都会开始认真工作。她把这个 \(t(p)\) 定义为 \(p\) 的检查时间。

可怜想知道所有 \(t(p)\) 的和。

但是这个结果可能很大,她想知道和对 \(10^9+7\) 取模后的结果。

sol

考虑 \(l=1\) 的部分分,会发现事实上只有取到 \(1\) 的时候游戏才会结束,所以要考虑取到所有的独特的、没有约数的数。

也就是 \(t(p)\) 是最后一个这样的数的位置。

讲问题转换发现只要求得 \(E[t(p)]\) 之后 \(\sum = E[t(p)]n!\) 就好了,而一个数排在所有关键点之后的概率是 \(\dfrac{1}{k+1}\) 的,可以用如下的方式理解:

\(k\) 个关键点可以把序列分成 \(k+1\) 段,而数在这些段落中随机分布。由于共有 \(n-k\) 个数,所以分布在之后的数的个数的期望是 \(\dfrac{n-k}{k+1}\)

最后再去最后的位置, \(n-\dfrac{n-k}{k+1}.\)

乘上 \(n!.\) 结束。

程式
#include <bits/stdc++.h>
#define ll long long
const int N=1e7+10,p=1e9+7;
using namespace std;
int n,m,l,R,k;
bitset<N> v;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin>>l>>R;
	for(int i=l;i<=R;++i)
		if(!v[i]){
			v[i]=true, ++k;
			for(int d=1;d*i<=R;++d) v[i*d]=true;
		}
	ll r=k;
	for(int i=1;i<=R-l+2;++i) r=r*(i==k+1?1:i)%p;
	cout<<r%p<<"\n";
	return 0;
}

P6835 线性生物

线形生物要从 \(1\) 号台阶走到 \(n+1\) 号台阶。

最开始,\(1,2,3,\ldots,n\) 号台阶都有一条连向下一台阶的有向边 \(i\rightarrow i+1\)

之后 Cirno 加入了 \(m\)返祖边 \(u_i \rightarrow v_i (u_i \ge v_i)\),它们构成了一个返祖图

线形生物每步会 等概率地 选取当前台阶的一条出边并走向对应的台阶。

当走到 \(n+1\) 号台阶时,线形生物就会停止行走。

同时,Cirno 会统计线性生物总共走的步数,记作 \(\delta\)

Cirno 想知道 \(E(\delta)\)(即 \(\delta\)数学期望)对 \(998244353\) 取模后的结果。

sol

其实不难。设 \(f(i)\) 为从 \(i\rightarrow i+1\) 的期望步数。设 \(i\) 有返祖边 \(m\) 条,分为 \(d_1,d_2,d_3,\cdots,d_m.\)\(g\)\(f\) 的前缀和。有:

\[f(i)=\dfrac{\sum_{j=1}^m (g_j-g_{d_j-1}+1)+1}{m+1} \]

利用 \(g_i=g_{i-1}+f(i)\),有

\[f(i)=-\sum_{j=1}^m (g_{d_j})+mg_{i-1}+m+1 \]

这时答案就是 \(g_n.\)

注意要多取模。

程式
#include <bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
typedef __int128 lint;
const ll p=998244353; 
const int N=1e6+10;
lint g[N],f[N];
ll id,n,m;
vector<ll> v[N];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin>>id>>n>>m;
	for(int i=1;i<=m;++i){
		int x,y;
		cin>>x>>y, v[x].push_back(y);
	}
	for(int i=1;i<=n;++i){
		lint M=v[i].size();
		for(int j=0;j<M;++j) f[i]=(f[i]-g[v[i][j]-1]+p)%p;
		f[i]=(f[i]+M*g[i-1]+M+1+p)%p, g[i]=(lint)(g[i-1]+f[i]+p)%p;
	}
	return cout<<(ll)((g[n]+p)%p)<<"\n",0;
}
posted @ 2024-05-03 16:53  ChihiroFujisaki  阅读(21)  评论(0)    收藏  举报