题意:有三个集合,分别含有a、b、c个点,要求给这些点连线,也可以全都不连,每两点距离为1,在同一集合的两点最短距离至少为3的条件下,问有多少种连接方案。
分析:
1、先研究两个集合,若每两个集合都保证满足条件,那最后结果一定满足条件。
2、两个集合间若要最短距离至少为3,那每个集合中的点只能同时与另一个集合中的一个点相连。
假设两个集合间需要连k条线,则可以在集合A中选k个点,在集合B中选k个点,共有k!种连接方式,即C[A][k] * C[B][k] * k!。
两个集合间最少可连0条,最多可连min(A,B),因此k的范围为0~min(A,B)。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const LL MOD = 998244353;
const double pi = acos(-1.0);
const int MAXN = 5000 + 10;
const int MAXT = 10000 + 10;
using namespace std;
LL C[MAXN][MAXN];
LL mul[MAXN];
void init(){
for(int i = 1; i <= 5000; ++i){
C[i][0] = C[i][i] = 1;
for(int j = 1; j < i; ++j){
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
}
}
mul[0] = 1;
for(int i = 1; i <= 5000; ++i){
mul[i] = (mul[i - 1] * i) % MOD;
}
}
LL solve(int x, int y){
int tmp = min(x, y);
LL ans = 0;
for(int i = 0; i <= tmp; ++i){
(ans += (((C[x][i] * C[y][i]) % MOD) * mul[i]) % MOD) %= MOD;
}
return ans;
}
int main(){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
init();
if(a < b) swap(a, b);
if(a < c) swap(a, c);
if(b < c) swap(b, c);
printf("%lld\n", (((solve(a, b) * solve(a, c)) % MOD) * solve(b, c)) % MOD);
return 0;
}