P6475 [NOI Online #2 入門組] 建設城市 題解

霸气的帝王蟹發表於2024-07-27

P6475 [NOI Online #2 入門組] 建設城市

傳送門

分類討論:
\(f(x, y)\)\(C^{j-1}_{i +j -1}\)

  1. \(x,y\)在同一旁
    \(x, y\)之間的看成一個高樓
    公式\(f(n,m)\times f(n+x-y,m)\)
  2. \(x, y\)在異側
    列舉\(x,y\)高樓的高度\(h\)
    \(\displaystyle \sum^{n}_{i=1}f(x-1,i)*f(n-x,m-i+1)*f(y-n-1,m-i+1)* f(2*n-y,i)\)

接著我們要處理的是\(f(x,y)\)

\[f(x,y)=C^{y-1}_{i +j-1}\\ C^n_m=\frac{m!}{n!(m-n)!} \]

如何\(O(1)\)查詢呢?
我們用\(O(n)\)時間預處理出階乘逆元

fac[0] = inv[0] = 1;
for (int i = 1; i <= M; ++i) fac[i]= (fac[i - 1] * i) % MOD;
inv[M] = Qpow(inv[M], MOD - 2);
for (int i = M - 1; i >= 1; --i) inv[i] = inv[i + 1] * (i + 1) % MOD;

查詢:

int C(int n, int m)
{ return fac[m] * inv[n] % MOD * inv[m - n] % MOD; }
int f(int n, int m)
{ return C(y - 1, i + j - 1); }

code :

#include <bits/stdc++.h>

#define int long long
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 998244353, N = 2e5 + 5, M = 2e5;
int fac[N], inv[N], ans;

int Qpow(int x, int y)
{
    int res = 1;
    for (; y; y /= 2, (x *= x) %= MOD)
        if (y & 1) (res *= x) %= MOD;
    return res;
}

int C(int n, int m)
{ return fac[m] * inv[n] % MOD * inv[m - n] % MOD; }
int f(int i, int j)
{ return C(j - 1, i + j - 1); }


signed main()
{
    fac[0] = inv[0] = 1;
    for (int i = 1; i <= M; ++i) fac[i]= (fac[i - 1] * i) % MOD;
    inv[M] = Qpow(fac[M], MOD - 2);
    for (int i = M - 1; i >= 1; --i) inv[i] = inv[i + 1] * (i + 1) % MOD;

    int m, n, x, y;
    scanf("%lld%lld%lld%lld", &m, &n, &x, &y);
    if (x <= n && y > n)
        for (int i = 1; i <= m; i++)
            ans = (ans + f(x - 1, i) * f(n - x, m - i + 1) % MOD * 
                    f(2 * n - y, i) % MOD * f(y - n - 1, m - i + 1) % MOD) % MOD;
    else ans = f(n, m) * f(n + x - y, m) % MOD;
    printf("%lld", ans);
    return 0;
}

相關文章