首先 “被经过的整点的期望个数” 不好求,我们可以把它看成 “每个整点被经过的概率的和”。
对于某个整点,求 “它被任意一个人经过的概率” 不好求,我们可以求 “它不被任意一个人经过的概率”,那么现在的问题是求某个整点不被某个人经过的概率,或者说求某个整点被某个人经过的概率。
把这个人看作原点,然后设这个整点的坐标为 i i i(不妨设 i ≥ 0 i\geq 0 i≥0, i < 0 i<0 i<0 同理)。考虑转化到坐标-时间图像上,现在问题转化为:从原点开始走,每一步能往右上/右下走,求走 n n n 步,过程中碰到直线 y = i y=i y=i 的走法方案数,最后除个 2 n 2^n 2n 即为概率。
(本文所有图片均引用自题解的 PPT)
类似卡特兰数,我们考虑翻折:对于一条碰到 y = i y=i y=i 且终点 j < i j<i j<i 的折线,我们找到它第一次碰到 y = i y=i y=i 的位置,并把这条折线在这个位置之后的所有部分都沿 y = i y=i y=i 做翻折,那么就得到了一条终点在 j ′ > i j'>i j′>i 的折线:
而且显然任意一条终点在 j ′ > i j'>i j′>i 的折线,都唯一对应着一条终点在 j ′ j' j′ 的折线(它自己),以及一条终点在 j j j 的折线(上述翻折过程的逆过程得到的折线)。
那么如果设
E
(
i
)
E(i)
E(i) 表示终点在
i
i
i 的走法方案数,那么碰到直线
y
=
i
y=i
y=i 的走法方案数即为:
E
(
i
)
+
2
∑
j
>
i
E
(
j
)
E(i)+2\sum_{j>i} E(j)
E(i)+2j>i∑E(j)
E
(
i
)
E(i)
E(i) 也比较好求:容易得到终点在
i
i
i 需要向上走
n
+
i
2
\frac{n+i}{2}
2n+i 步,于是
E
(
i
)
=
[
n
≡
i
(
m
o
d
2
)
]
(
n
n
+
i
2
)
E(i)=[n\equiv i\pmod 2]\dbinom{n}{\frac{n+i}{2}}
E(i)=[n≡i(mod2)](2n+in)。
那么我们直接枚举每一个可能经过的整点( O ( n m ) O(nm) O(nm) 个),再对枚举的整点枚举每一个人,时间复杂度 O ( n m 2 ) O(nm^2) O(nm2)。
#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
*/