CF 869C. The Intriguing Obsession


The Intriguing Obsession

题意

\(3\) 个群岛,这三个群岛分别有 \(a、b、c\) 个岛屿。

现在要在这些岛之间连桥,要求每个群岛中的任意两个岛屿。要么不能联通,要么最短路为 \(3\) 。求允许建桥的所有方案数量。

分析

先对两个群岛进行分析,因为在一个群岛中,任意两个岛屿都不能相连,或者最短路为3。这就意味着,首先这两个岛屿不能直接相连,其次,一个岛屿不能连接另外一个群岛内的两个岛屿。也就是说桥只能建在群岛之间,且必须是一一映射的。

对于 \(a, b\) 两个数量的群岛,最多可以建 \(m = min(a, b)\) 座桥,假设现在需要建 \(k\) 个桥,从 \(a\) 群岛选择 \(k\) 个岛屿的方案为 \(C(a, k)\) ,从 \(b\) 群岛选择 \(k\) 的岛屿的方案为 \(C(b, k)\) ,映射的方案数为 \(k!\) 个,所以此时总方案数为 \(C(a, k) \times C(b, k) \times k!\)

对于三个岛屿,由于最短路为 \(3\) ,所以就是三种情况乘起来。

Code

#include 
#include 
using namespace std;

typedef long long ll;

const int N = 5010, mod = 998244353;

int fac[N], C[N][N];
long long ret;

void get (int a, int b)
{
    int m = min(a, b), ans;
    for (int k = 0; k <= m; k ++ )
        ans = (ans + (ll) C[a][k] * C[b][k] % mod * fac[k] % mod) % mod;
    ret = (ll) ret * ans % mod;
}

int main ()
{
    int a, b, c; cin >> a >> b >> c;
    fac[0] = 1;
    for (int i = 1; i <= 5000; i ++ ) fac[i] = (ll) i * fac[i-1] % mod;
    
    C[0][0] = 1;
    for (int i = 1; i <= 5000; i ++ )
        for (int j = 0; j <= 5000; j ++ )
            if (!j) C[i][j] = 1;
            else C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
    
    ret = 1;
    get(a, b); get(a, c); get(b, c);
    cout << ret << endl;
    return 0;
}