一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
考虑一种颜色的结点能怎样连边
如果连了两个相同颜色的结点,那么非法了
如果连了最多两个不同颜色的结点,那么网络中任意两个相同颜色结点之间举例至少是3
所以我们边可以分为3类:
A-B A-C B-C
分别计算三种边的数目然后乘一下就行
由于这是个组合问题也是个排列问题
对于颜色a,b而言,其边数为ΣC(a, i)C(b, i) * i!
我们可以杨辉三角处理组合数,也可以乘法逆元处理,可以降低到O(n)
2、复杂度
时间复杂度:O(n) 空间复杂度:O(n)
3、代码详解
#include <bits/stdc++.h>
const int mod = 998'244'353, N = 5005;
int fac[N], invfac[N], ab, ac, bc;
int qp(int a,int b)
{
int res = 1;
while(b)
{
if(b & 1)
res = 1LL * res * a % mod;
b >>= 1, a = 1LL * a * a % mod;
}
return res;
}
int C(int n,int m)
{
if(n == m)
return 1;
return ((1LL * fac[n] * invfac[m] % mod) * invfac[n - m]) % mod;
}
int calc(int a, int b) {
int res = 1;
for(int k = 1, ed = std::min(a, b); k <= ed; k ++)
res = (res + (((1LL * C(a, k) * C(b, k)) % mod) * fac[k]) % mod) % mod;
return res;
}
int main()
{
int a, b, c;
std::cin >> a >> b >> c;
int n = std::max( {a, b, c} );
fac[0] = 1;
for(int i = 1; i <= n; i ++)
fac[i] = 1LL * fac[i - 1] * i % mod;
invfac[n] = qp(fac[n], mod - 2);
for(int i = n - 1; i; i --)
invfac[i] = 1LL * invfac[i + 1] * (i + 1) % mod;
ab = calc(a, b), ac = calc(a, c), bc = calc(b, c);
std::cout << ((((1LL * ab * ac) % mod) * bc) % mod);
return 0;
}