【XSY3395】逃亡(概率与期望,组合数)

首先 “被经过的整点的期望个数” 不好求,我们可以把它看成 “每个整点被经过的概率的和”。

对于某个整点,求 “它被任意一个人经过的概率” 不好求,我们可以求 “它不被任意一个人经过的概率”,那么现在的问题是求某个整点不被某个人经过的概率,或者说求某个整点被某个人经过的概率。

把这个人看作原点,然后设这个整点的坐标为 \(i\)(不妨设 \(i\geq 0\)\(i<0\) 同理)。考虑转化到坐标-时间图像上,现在问题转化为:从原点开始走,每一步能往右上/右下走,求走 \(n\) 步,过程中碰到直线 \(y=i\) 的走法方案数,最后除个 \(2^n\) 即为概率。

在这里插入图片描述

(本文所有图片均引用自题解的 PPT)

类似卡特兰数,我们考虑翻折:对于一条碰到 \(y=i\) 且终点 \(j<i\) 的折线,我们找到它第一次碰到 \(y=i\) 的位置,并把这条折线在这个位置之后的所有部分都沿 \(y=i\) 做翻折,那么就得到了一条终点在 \(j'>i\) 的折线:

在这里插入图片描述

而且显然任意一条终点在 \(j'>i\) 的折线,都唯一对应着一条终点在 \(j'\) 的折线(它自己),以及一条终点在 \(j\) 的折线(上述翻折过程的逆过程得到的折线)。

那么如果设 \(E(i)\) 表示终点在 \(i\) 的走法方案数,那么碰到直线 \(y=i\) 的走法方案数即为:

\[E(i)+2\sum_{j>i} E(j) \]

\(E(i)\) 也比较好求:容易得到终点在 \(i\) 需要向上走 \(\frac{n+i}{2}\) 步,于是 \(E(i)=[n\equiv i\pmod 2]\dbinom{n}{\frac{n+i}{2}}\)

那么我们直接枚举每一个可能经过的整点(\(O(nm)\) 个),再对枚举的整点枚举每一个人,时间复杂度 \(O(nm^2)\)

#include<bits/stdc++.h>

#define M 25
#define N 12000010
#define fi first
#define se second
#define pii pair<int,int>
#define mk(a,b) make_pair(a,b)
#define INF 0x7fffffff

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 n,m,x[M];
int fac[N],ifac[N],E[N];

vector<pii>part;

int C(int n,int m)
{
	return mul(mul(fac[n],ifac[m]),ifac[n-m]);
}

int calc(int now)
{
	int p=1;
	for(int i=1;i<=m;i++)
		if(abs(now-x[i])<=n)
			p=mul(p,dec(1,E[abs(now-x[i])]));
	return dec(1,p);
}

int main()
{
	n=read(),m=read();
	int inv=poww(poww(2,n),mod-2);
	fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
	ifac[n]=poww(fac[n],mod-2);
	for(int i=n;i>=1;i--) ifac[i-1]=mul(ifac[i],i);
	int sum=0;
	for(int i=n;i>=0;i--)
	{
		int nowE=0;
		if(!((i&1)^(n&1))) nowE=mul(inv,C(n,(n+i)/2));
		E[i]=add(nowE,mul(sum,2));
		sum=add(sum,nowE);
	}
	for(int i=1;i<=m;i++)
	{
		x[i]=read();
		part.push_back(mk(x[i]-n,x[i]+n));
	}
	sort(part.begin(),part.end());
	int lstr=-INF,ans=0;
	for(pii now:part)
	{
		int l=now.fi,r=now.se;
		l=max(l,lstr+1);
		for(int i=l;i<=r;i++)
			ans=add(ans,calc(i));
		lstr=max(lstr,r);
	}
	printf("%d\n",ans);
	return 0;
}
/*
2 1
1
*/
posted @ 2022-10-30 11:01  ez_lcw  阅读(15)  评论(0编辑  收藏  举报