ABC405E: Fruit Lineup

解法

\(f(n,m)\) 表示将 \(m\) 个字母插入到 \(n\) 个空隙之中。

\(f(n,m)=C_{n+m-1}^{n-1}\)

证明

可以发现 \(f\) 就相当于将 \(m\) 个苹果放到 \(n\) 个盒子里。
通过栅栏法,可以推断出该式等于 \(C_{n+m-1}^{n-1}\)

首先,我们把 \(A\)\(D\) 先排成 \(AAA\dots DDD\dots\) 这样。

接下去再枚举在 \(A\)\(D\) 中间的 \(B\) 的数量 \(x\)

然后在计算剩余的 \(B\) 放入 \(A\) 当中的方案数 \(f(A,B-x)\)

最后在计算将 \(C\) 插入到 \(A\) 后面的方案数 \(f(D+x+1,c)\)

再两两相乘再相加即可

代码

#include <bits/stdc++.h>
#define int long long
const int N = 3e6 + 5;
const int Mod = 998244353;
using namespace std;
int a, b, c, d;
int ans;
int fac[N], ifac[N];
int qpow(int a, int b)
{
    int res = 1;
    while (b > 0)
    {
        if (b & 1)
        {
            res = res * a;
            res %= Mod;
        }
        a = a * a;
        a %= Mod;
        b >>= 1;
    }
    return res;
}
void init()
{
    fac[0] = 1;
    for (int i = 1; i < N; i++)
    {
        fac[i] = fac[i - 1] * i;
        fac[i] %= Mod;
    }
    ifac[N - 1] = qpow(fac[N - 1], Mod - 2);
    for (int i = N - 2; i >= 0; i--)
    {
        ifac[i] = ifac[i + 1] * (i + 1);
        ifac[i] %= Mod;
    }
}
int A(int n, int m)
{
    if (m < 0 || m > n)
    {
        return 0;
    }
    return fac[n] * ifac[m] % Mod;
}
int C(int n, int m)
{
    if (m < 0 || m > n)
    {
        return 0;
    }
    return fac[n] * ifac[m] % Mod * ifac[n - m] % Mod;
}
int f(int n, int m)
{
    return C(n + m - 1, n - 1);
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    init();
    cin >> a >> b >> c >> d;
    for (int i = 0; i <= b; i++)
    {
        ans += f(a, b - i) * f(d + i + 1, c) % Mod;
        ans %= Mod;
    }
    cout << ans;
    return 0;
}

提交记录

posted @ 2025-05-13 21:57  jackzhang2013  阅读(33)  评论(0)    收藏  举报