ARC124F Chance Meeting 题解
题意
两个人在 \(n\times m\) 网格图中走,一个人从 \((1,1)\) 到 \((n,m)\) ,另一人从 \((n,1)\) 到 \((1,m)\) ,每次操作可以让一人向目的地方向水平或竖直靠近一步,求让两人恰好相遇一次的方案数 \(\bmod 998244353\) 。
\((2\le n,m\le2\times10^5)\)
题解
首先将 \(n,m\) 均减 \(1\) ,坐标从 \(0\) 开始方便讨论。
恰好显然不太方便,考虑算一个两人在 \((i,j)\) 处相遇一次的方案。
注意到 \(j\) 是多少方案都一样,所以列影响不大,最后乘上 \(\binom{2n}{n}\) 的系数即可。
现在设 \(g(i)\) 为在 \((n,i)\) 相遇的方案数,显然 \(\binom{n+2i}{2i}\binom{2i}{i}\) 。
现在计算 \(f(i)\) 为仅在 \((n,i)\) 相遇的方案数,考虑容斥计算:
\[f(i)=g(i)-\sum_{i=0}^{k-1}2g(i)c(i-k-1)
\]
其中 \(c(i)\) 为卡特兰数,表示一个人先走一步,之后另一个人不能和他走的一致。
卷一卷就能算了。
答案: \(\sum_{i=0}^{n}\binom{2n}{n}f(i)f(n-i)\) 。
时间复杂度: \(O(n\log n)\) 。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=1e6,g=3,ig=332748118,mod=998244353;
int ans,p[N],inv[N],c[N],f[N];
inline int qpow(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll*res*x%mod;
x=1ll*x*x%mod;y>>=1;
}
return res;
}
void ntt(int*a,int n,bool fl){
int ni=qpow(n,mod-2);
for(int i=0,j=0;i<n;i++){
if(j>i) swap(a[i],a[j]);
int k=n;
while(j&(k>>=1)) j&=~k;
j|=k;
}
for(int i=1;i<n;i<<=1){
int t=qpow(fl?ig:g,(mod-1)/i/2);
for(int j=0;j<n;j+=i<<1)
for(int k=j,now=1;k<j+i;k++,now=1ll*now*t%mod){
int nk=k+i,p=1ll*now*a[nk]%mod;
a[nk]=(a[k]-p+mod)%mod;(a[k]+=p)%=mod;
}
}
if(fl) for(int i=0;i<n;i++) a[i]=1ll*a[i]*ni%mod;
}
void mul(int n1,int n2,int*f1,int*f2){
int n=2;
while(n<=n1+n2) n<<=1;
ntt(f1,n,0);ntt(f2,n,0);
for(int i=0;i<n;i++) f1[i]=1ll*f1[i]*f2[i]%mod;
ntt(f1,n,1);ntt(f2,n,1);
}
int C(int n,int m) {return 1ll*p[n]*inv[m]%mod*inv[n-m]%mod;}
signed main(){
p[0]=inv[0]=1;
for(int i=1;i<N;i++) p[i]=1ll*p[i-1]*i%mod;
inv[N-1]=qpow(p[N-1],mod-2);
for(int i=N-2;i;i--) inv[i]=(i+1ll)*inv[i+1]%mod;
int n,m;scanf("%d%d",&n,&m);n--;m--;
for(int i=0;i<=m;i++) f[i]=1ll*C(n+i*2,i*2)*C(i*2,i)%mod;
for(int i=0;i<=m;i++) c[i]=2ll*C(i*2,i)*inv[i+1]%mod*p[i]%mod;
mul(m,m,c,f);f[0]=1;
for(int i=1;i<=m;i++) (f[i]+=mod-c[i-1])%=mod;
for(int i=0;i<=m;i++) (ans+=1ll*f[i]*f[m-i]%mod)%=mod;
printf("%lld\n",1ll*ans*C(n*2,n)%mod);
return 0;
}

浙公网安备 33010602011771号