两道类似的概率期望题目

前几周的模拟赛才遇到过类似的套路,现在在 AT 上遇到又不会了……于是都记录一下。

其实写完之后还是感觉不太能熟练运用……,可能需要多做题做理解。

【XSY4214】quq

题面:http://192.168.102.138/JudgeOnline/problem.php?cid=1818&pid=2

题解:

\(m=\max a_i\),即编号最大的可能被扭到的蛋。

首先先将扭蛋机按 \(a_i\) 从小到大排序。先考虑最优策略是什么,设 \(b_i\) 表示 \(\geq i\) 的最小的 \(a\) 值,那么假设现在还未扭到的蛋的集合是 \(S\),其中编号最大的是 \(maxid\),那么我们选的扭蛋机大小肯定是 \(b_{maxid}\)。感性理解就是扭编号大的扭蛋时也有可能扭到编号小的扭蛋,而扭编号小的扭蛋时不可能扭到编号大的扭蛋,所以如果先扭编号小的扭蛋再扭编号大的扭蛋,就会在扭编号大的扭蛋时浪费更多的期望次数,所以我们要选能扭到所有扭蛋且 \(a\) 值最小的扭蛋机。

由于扭哪个扭蛋机是由 \(maxid\) 决定的,所以我们枚举每个扭蛋 \(x\),计算出它作为 \(maxid\) 出现出现的概率以及它作为 \(maxid\) 出现时,使得 \(maxid\) 改变(即扭到它)的期望扭蛋次数。

期望扭蛋次数即为 \(b_{x}\),现在关键问题是求出 \(x\) 作为 \(maxid\) 出现的概率,即操作完 \(x+1\sim m\) 时还没有扭到 \(x\) 的概率。

对于任意一个时刻,当前还未扭到的蛋的集合为 \(S\),那么对于所有 \(i\in S\),下一个扭到的未出现过的蛋为 \(i\) 的概率都是相同的。也就是说如果我们只看每一个蛋第一次被扭出的时间的顺序,那么每一种顺序(\(1\sim m\) 的每一种排列)的出现概率都是相同的。

那么操作完 \(x+1\sim m\) 时还没有扭到 \(x\) 的概率,就相当于在这个 \(1\sim m\) 的排列中 \(x\) 出现位置比 \(x+1\sim m\) 都要靠后的概率,即为 \(\frac{1}{m-x+1}\)

【ARC114E】Paper Cutting 2

题意:你有一张大小为 \(H\times W\) 的长方形纸,被划分为 \(H\times W\) 个格子,其中有恰好两个格子是黑色的,其余都是白色的。你需要进行如下操作:

  • 假设你当前还剩下一张大小为 \(h\times w\) 的纸,那么这张纸被 \(h-1\) 条横线和 \(w-1\) 条竖线划分为 \(h\times w\) 个格子,你将在这 \(h+w-2\) 条线中随机选择一条,并沿着这一条线将整张纸剪开剪成两张纸,然后:
    • 如果两个黑色格子仍然在同一张纸上,则扔掉另一张纸,重复执行上述操作。
    • 否则结束操作。

求期望进行的操作次数,对 \(998244353\) 取模。

\(H,W\leq 10^5\)

题解:

先讲一维的情况。假设纸条长度为 \(n\)(有 \(n\) 个格子),两个黑格子分别是 \(x,y\)\(x<y\))。

第一想法是 \(O(n^3)\) 的 DP(记录两个黑格子两边剩余的格子数),但貌似不太能做,因为状态数已经是 \(O(n^2)\) 的了。

难点在于这个概率可能比较难处理,毕竟纸条剩余长度不同概率就不同。

一个非常高妙的转化是:题目等价于,我们随机一个 \(1\sim n-1\) 的排列,并按随机出的排列顺序切纸条,切的过程中只有合法才计数(不合法的情况有:当前切线所在纸条已经和黑格子分离了、两个黑格子之前就已经被切开了等),求切的次数的期望。

证明是不难的,假设已经切到了某种状态(确定了排列的前若干位),对于下一步可能的每种合法的切法,它们成为下一步(在后面的排列中作为第一个合法的切法出现)的概率是相等的。

现在我们只需要统计切的次数的期望即可。

这是简单的,枚举切第 \(i\) 条线的贡献,合法的条件是:\(i\) 到黑格子之间、黑格子与黑格子之间没有线被切过。假设需要某 \(k\) 条线不被切过,那么第 \(i\) 条线的贡献就是 \(\frac{1}{k+1}\)

这个转化大概思路就是:考虑把不合法的操作也加入操作序列内填充成一个排列,使得每种操作序列出现的概率不变(基数增大但概率不变),而对排列来说概率是好求的。

二维的情况也是类似的,事实上貌似可以扩展到 \(n\) 维?

#include<bits/stdc++.h>

using namespace std;

namespace modular
{
	const int mod=998244353;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;

inline int poww(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

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<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int H,W,h1,w1,h2,w2;

int main()
{
	H=read(),W=read(),h1=read(),w1=read(),h2=read(),w2=read();
	if(h1>h2) swap(h1,h2);
	if(w1>w2) swap(w1,w2);
	int ans=0;
	for(int i=1;i<H;i++)
	{
		int k;
		if(i<h1) k=h1-1-i+h2-h1;
		else if(i<h2) k=h2-h1-1;
		else k=i-h2+h2-h1;
		k+=w2-w1;
		ans=add(ans,poww(k+1,mod-2));
	}
	for(int i=1;i<W;i++)
	{
		int k;
		if(i<w1) k=w1-1-i+w2-w1;
		else if(i<w2) k=w2-w1-1;
		else k=i-w2+w2-w1;
		k+=h2-h1;
		ans=add(ans,poww(k+1,mod-2));
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-10-31 08:40  ez_lcw  阅读(49)  评论(0编辑  收藏  举报