Atcoder 124F Chance Meeting
Problem Statement
Given is a grid with H rows and W columns. Let (i,j)denote the square at the i-th row from the top and j-th column from the left.
Initially, a camel is on (1,1), and a cat is on (H,1).
You can send the following four kinds of orders.
R
: Move the camel on (i,j) to (i,j+1)D
: Move the camel on (i,j) to (i+1,j).r
: Move the cat on (i,j) to (i,j+1).u
: Move the cat on (i,j) to (i−1,j).
A sequence of orders satisfying all of the four conditions below is said to be good. Find the number of good sequences of orders, modulo 998244353.
- The final position of the camel will be (H,W).
- The final position of the cat will be (1,W).
- The following will happen exactly once: the camel and the cat are on the same square after an order is processed.
- Neither the camel nor the cat will leave the grid.
Constraints
- All values in input are integers.
- 2≤H,W≤2×105
Input
Input is given from Standard Input in the following format:
H W
Output
Print the number of good sequences of orders, modulo 998244353.
Sample Input 1 Copy
2 2
Sample Output 1 Copy
16
- The good sequences of orders include
DRur
,DurR
,RruD
,RDru
, but notDRru
,RRR
.
Sample Input 2 Copy
200000 200000
Sample Output 2 Copy
412709667
- Be sure to print the count modulo 998244353.
题目翻译
\(H\)行\(W\)列的方格,一个骆驼位于\((1,1)\),一只猫位于\((H,1)\)
有以下4种操作
- R:骆驼向右移动
- D:骆驼向下移动
- r:猫向右移动
- u:猫向上移动
求猫与骆驼仅相遇一次,且骆驼最终位于\((H,W)\),猫位于\((1,W)\)的方案数
题目解析
首先是, n,m 均减一,从格子数转换为横竖的步数
无论怎么走,n次竖直操作后,必定在同一行
设\(f(i)\)表示在\((x,i)\)第一次相遇方案数,总答案为\(\sum_{i=0}^{m}\C_{2n}^{n}f(i)f(m-i)\)
考虑使用容斥接触“第一次”的限制,设\(g(i)\)表示在\((x,i)\)不一定是第一次相遇的方案数,有\(g(i)=\C_{2i+n}^{2i}\C_{2i}^{i}\)
显然\(f(i)\)与\(g(i)\)关系满足\(f(i)=g(i)-C\)
其中\(C\)多出了在\((x,i)\)之前相遇的方案数,枚举前一次在\((x,k)\)相遇的方案,在\(g(i)\)中减去:
\(f(i)=g(i)-\sum_{k=0}^{k-1}g(k)*2*Catalan(i-k-1)\)
因为有2个人,所以不同人领先的情况要乘\(2\)
后面的式子可以卷积,用NTT处理
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
int Mod=998244353;
int G=3;
const int maxn=2e5*4+5;
int R[2*maxn],n,m,fac[maxn],invfac[maxn];
int g[maxn],catalan[maxn],f[200005],ans;
int qpow(int x,int k){
int res=1;
while (k){
if (k&1) res=1ll*res*x%Mod;
x=1ll*x*x%Mod;
k>>=1;
}
return res;
}
void NTT(int *A, int len, int o)
{
int wn, w, i, j, k, x, y;
for (i = 0; i < len; i++)
if (i < R[i])
swap(A[i], A[R[i]]);
for (i = 1; i < len; i <<= 1)
{
wn = qpow(G, (Mod - 1) / (i << 1));
if (o == -1)
wn = qpow(wn, Mod - 2);
for (j = 0; j < len; j += (i << 1))
{
w = 1;
for (k = 0; k < i; k++, w = 1ll * w * wn % Mod)
{
x = A[j + k];
y = 1ll * w * A[j + k + i] % Mod;
A[j + k] = x + y;
if (A[j + k] >= Mod)
A[j + k] -= Mod;
A[j + k + i] = x - y;
if (A[j + k + i] < 0)
A[j + k + i] += Mod;
}
}
}
if (o == -1)
{
int tmp = qpow(len, Mod - 2);
for (i = 0; i < len; i++)
A[i] = 1ll * A[i] * tmp % Mod;
}
}
int getC(int x,int y){
if (x<y) return 0;
return 1ll*fac[x]*invfac[y]%Mod*invfac[x-y]%Mod;
}
void pre(){
fac[0]=1;
for (int i=1;i<=maxn;i++)
fac[i]=1ll*fac[i-1]*i%Mod;
invfac[maxn]=qpow(fac[maxn],Mod-2);
invfac[0]=1;
for (int i=maxn-1;i>=1;i--){
invfac[i]=1ll*invfac[i+1]*(i+1)%Mod;
}
}
int main()
{
int lg=0,len=1;
pre();
cin>>n>>m;
n--;m--;//n*m转换为步数就是n-1,m-1
while (len<=2*m) len*=2,lg++;
for (int i=0;i<len;i++)
R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1));
for (int i=0;i<=m;i++){
g[i]=1ll*getC(2*i+n,2*i)*getC(2*i,i)%Mod;
//cout<<g[i]<<" ";
}
//cout<<endl;
for (int i=0;i<=m;i++){
catalan[i]=1ll*getC(2*i,i)*invfac[i+1]%Mod*fac[i]%Mod;
//cout<<catalan[i]<<" ";
}
//cout<<endl;
NTT(g,len,1);NTT(catalan,len,1);
for (int i=0;i<len;i++)
catalan[i]=1ll*catalan[i]*g[i]%Mod;
NTT(catalan,len,-1);NTT(g,len,-1);
f[0]=1;
for (int i=1;i<=m;i++){
f[i]=(g[i]-2ll*catalan[i-1]%Mod+Mod)%Mod;
//cout<<f[i]<<" ";
}
//cout<<endl;
ans=0;
for (int i=0;i<=m;i++){
ans=(ans+1ll*f[i]*f[m-i]%Mod)%Mod;
}
ans=1ll*ans*getC(2*n,n)%Mod;
cout<<ans;
}