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 <iostream>
#include <algorithm>
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;
}