组合数学,cf869C. The Intriguing Obsession

一、题目

1、题目描述

2、输入输出

2.1输入

2.2输出

3、原题链接

Problem - 869C - Codeforces


二、解题报告

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值