前几周的模拟赛才遇到过类似的套路,现在在 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;
}
标签:概率,期望,格子,int,扭蛋,maxid,编号,题目,两道
From: https://www.cnblogs.com/ez-lcw/p/16843073.html