此题算法:模拟。
题目概述
由题意可得,此题是让我们连接三种不同颜色的点,
要求同颜色的点距离大于等于 3 (每条边的距离为 1 ),
任意两个点至多连 1 条边,
问有多少种连接方案(答案需取模)。
Part 1 - 主要思路
首先,
因为:同颜色的点距离大于等于 3 ,
所以我们可以得出:
-
显然,一个点不能与它同色的点相连;
-
一个点不能同时与两个同色点相连。
综上,
只有 3 种连接方案—— a 与 b , b 与 c , a 与 c 。
且! 3 种连接方案都是独立的。
接着,我们就只用计算每两种颜色最多可以有多少种连接方案。
Part 2 - 计算方案
举一个栗子:求 a 与 b 连接的方案总数。
总数 = 从 a 与 b 中各挑 0 个的方案数 +
各挑 1 个的方案数 + 各挑 2 个的方案数 + ······ + 各挑
m
i
n
(
a
,
b
)
min (a, b)
min(a,b) 的方案数 。
且,
从 a 与 b 中各挑 i 个方案数 = 从 a 中挑 i 个数的方案数 ∗ * ∗ 从 b 中挑 i 个数的方案数 ∗ * ∗ i 个数的排列情况总数。
这个, 不就是我们小学就学过的排列组合 + 阶乘吗?
Part 3 - 计算 + 完善
1 . 排列组合计算:
用二维数组 C [ i ] [ j ] C[i][j] C[i][j] 来模拟组合的计算,
表示从 i 个里面挑 j 个数。
通过我们又在小学就学过的杨辉三角可以对数组 C 进行预处理,后面直接用即可。
特别注意:不要忘记还有从 0 个里面挑 0 个的情况,这个直接特殊处理,在最后的时候再加上即可。
2 . i 个数排列情况计算:
这个相对 1 来说就简单多了,情况总数 = i 的阶乘。
类似 1 里面的处理方法,我们用数组 jc (请原谅我的变量名) 进行预处理,后面直接用即可。
3 . 最终完善:
最后的答案就是三种情况的数量相乘,不要忘记取模!!!
最后的最后:
记得开 l o n g l o n g longlong longlong 。
C o d e Code Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a, b, c;
const int Mod = 998244353;
const int maxn = 5005;
int jc[maxn];
int C[maxn][maxn];
int maxx;
inline void jc_init ()
{
jc[1] = 1;
for (int i = 2; i <= maxx; i++) jc[i] = (jc[i - 1] * i) % Mod;
}
inline void C_init ()
{
C[0][0] = 1;
for (int i = 1; i <= maxx; i++)
for (int j = 0; j <= i; j++)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % Mod;
}
inline int calcu (int x, int y)
{
int res = 1;
int minn = min (x, y);
for (int i = 1; i <= minn; i++)
res = (res + C[x][i] * C[y][i] % Mod * jc[i] % Mod) % Mod;
return res;
}
signed main()
{
scanf ("%lld%lld%lld", &a, &b, &c);
maxx = max (a, max (b, c));
jc_init ();
C_init ();
printf ("%lld\n", calcu (a, b) * calcu (b, c) % Mod * calcu (c, a) % Mod);
return 0;
}
E n d End End