[Codeforces 869C]The Intriguing Obsession(组合数学)

Address

http://codeforces.com/problemset/problem/869/C

Meaning

有三种不同类型的小岛,方便地,各自涂上了红,蓝,紫三色。每种颜色的小岛各自有 a a b c c 个。
这些小岛之间初始时互相分离。可以在小岛之间架桥,两个小岛间最多架一座桥。
但要满足:任意两个不同的颜色相同的小岛的最短距离要大于等于 3 (桥的长度为 1 1 )。
你需要计算出不同的架桥方案有多少种,如果有两个小岛之间造桥的方案变了,我们就说这两个造桥的方案不同。答案对 998244353 取模。
1a,b,c5000 1 ≤ a , b , c ≤ 5000

Solution

第一眼发现「最短距离大于等于 3 3 」不容易做。
可以把它转化为「最短距离不小于等于 2 」。
转化了有什么用呢?可以将条件等价化为:
(1)任意两个同色的点之间没有边。
(2)任意一个点 u u 发出的任意两条边 (u,v)(u,w) 的另一端 v,w v , w 异色。
于是我们先在红色和蓝色的点之间连边,然后在红色和紫色的点之间连边,最后在蓝色和紫色的点之间连边。
假设在红色的点中选出了指定的 i i 个点,将这 i 个红色点分别与 i i 个蓝色点连边,这样的方案数显然为 Abi
所以,在红色和蓝色点之间连边的方案数为:

i=0min(a,b)CiaAib ∑ i = 0 min ( a , b ) C a i A b i

到这里,最终答案也得出了:
(i=0min(a,b)CiaAib)(i=0min(a,c)CiaAic)(i=0min(b,c)CibAic) ( ∑ i = 0 min ( a , b ) C a i A b i ) ( ∑ i = 0 min ( a , c ) C a i A c i ) ( ∑ i = 0 min ( b , c ) C b i A c i )

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
using namespace std;
const int N = 5005, PYZ = 998244353;
int a, b, c, fac[N], inv[N], ans1, ans2, ans3;
int A(int n, int m) {
    return 1ll * fac[n] * inv[n - m] % PYZ;
}
int C(int n, int m) {
    return 1ll * fac[n] * inv[m] % PYZ * inv[n - m] % PYZ;
}
int main() {
    int i; cin >> a >> b >> c; fac[0] = 1;
    For (i, 1, 5000) fac[i] = 1ll * fac[i - 1] * i % PYZ;
    inv[0] = inv[1] = 1;
    For (i, 2, 5000)
        inv[i] = 1ll * (PYZ - PYZ / i) * inv[PYZ % i] % PYZ;
    For (i, 2, 5000) inv[i] = 1ll * inv[i] * inv[i - 1] % PYZ;
    For (i, 0, min(a, b))
        ans1 = (ans1 + 1ll * C(a, i) * A(b, i) % PYZ) % PYZ;
    For (i, 0, min(a, c))
        ans2 = (ans2 + 1ll * C(a, i) * A(c, i) % PYZ) % PYZ;
    For (i, 0, min(b, c))
        ans3 = (ans3 + 1ll * C(b, i) * A(c, i) % PYZ) % PYZ;
    cout << 1ll * ans1 * ans2 % PYZ * ans3 % PYZ << endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值