zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    【HDU4676】Sum Of Gcd(莫队+欧拉函数)
    【BZOJ5084】hashit(后缀自动机水过)
    【HHHOJ】ZJOI2019模拟赛(十三)03.10 解题报告
    【BZOJ2127】happiness(网络流)
    【CCPC-Wannafly Winter Camp Day4 (Div1) J】跑跑跑路(爬山算法)
    【CCPC-Wannafly Winter Camp Day4 (Div1) H】命命命运(概率DP)
    2019.03.09 ZJOI2019模拟赛 解题报告
    关闭Android/iPhone浏览器自动识别数字为电话号码
    border-radius 在安卓手机竟然不完美支持
    validate.plugin.js 验证插件
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/15135346.html
Copyright © 2011-2022 走看看