题目链接
题意:
有3个群岛,每个群岛中有一些互不相同的岛屿,现在建一些桥,使得同一群岛内的两个岛屿要么不连通要么最短路至少经过3条桥。给定三个群岛包含的岛数,求合法的建桥的方案数。
思路:
不连通很好考虑,我们直接不允许相同的岛屿连边就好了.
考虑最短路至少3条,也就是说同一种岛屿不能同时和其他另一种岛屿两个或以上连边,否则就不满足条件.
那么我们将三种岛屿两两考虑,找出两两岛屿连边的情况,然后根据乘法原理求出答案即可.
上述问题可以抽象成:
f(x,y) (x<= y) x个不同的小球,放到y个不同的盒子中,(每个盒子最多放一个,允许小球有剩余)的方法数.
f(x,y)=∑xk=0C(x,k)y!(y−k)!
最终答案即为 f(a,b)*f(b,c)*f(a,c)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e3+5;
const int mod =998244353;
ll c[maxn][maxn],fac[maxn] = {1},inv[maxn] = {1};
ll qmod(ll a,ll b)
{
ll res = 1;
while(b)
{
if(b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res % mod;
}
void init()
{
c[0][0] = 1;
for(int i = 1;i < maxn;++i)
for(int j = 0;j <= i ;++j)
{
if(!j) c[i][j] = 1;
else c[i][j] = (c[i-1][j]+c[i-1][j-1]) % mod;
}
for(int i = 1;i < maxn;++i)
{
fac[i] = fac[i-1]*i % mod;
inv[i] = qmod(fac[i],mod-2);
//printf("%lld %lld\n",fac[i],inv[i]);
}
return ;
}
int main()
{
int s[3];
init();
while(~scanf("%d %d %d",&s[0],&s[1],&s[2]))
{
sort(s,s+3);
ll ans = 1;
for(int i = 0;i < 3; ++i)
{
for(int j = i + 1;j < 3; ++j)
{
ll tmp = 0;
for(int k = 0;k <= s[i];++k)
{
tmp = (tmp + c[s[i]][k]*fac[s[j]]%mod*inv[s[j]-k] % mod) %mod;
}
ans = ans*tmp % mod;
}
}
printf("%lld\n",ans);
}
return 0;
}