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.

  1. The final position of the camel will be (H,W).
  2. The final position of the cat will be (1,W).
  3. The following will happen exactly once: the camel and the cat are on the same square after an order is processed.
  4. 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 not DRru, 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;
}
posted @ 2021-08-12 23:13  Z-Y-Y-S  阅读(67)  评论(0编辑  收藏  举报