zoukankan      html  css  js  c++  java
  • [CF869C] The Intriguing Obsession

    [CF869C] The Intriguing Obsession - 组合,二分图匹配

    Description

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

    Solution

    相当于是红蓝、蓝紫、紫红之间的二分图匹配方案数(不需要最大匹配)

    以 a,b 为例

    我们枚举匹配答案 i 从 0 到 min(a,b),这样相当于是两个组合数的乘积乘上一个全排列

    最后三个部分的方案数相乘就是答案

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int mod = 998244353;
    
    namespace math_mod
    {
        int c__[5005][5005], fac__[5005];
    
        int qpow(int p, int q)
        {
            return (q & 1 ? p : 1) * (q ? qpow(p * p % mod, q / 2) : 1) % mod;
        }
    
        int inv(int p)
        {
            return qpow(p, mod - 2);
        }
    
        int fac(int p)
        {
            if (p <= 5000)
                return fac__[p];
            if (p == 0)
                return 1;
            return p * fac(p - 1) % mod;
        }
    
        int __fac(int p)
        {
            return fac(p);
        }
    
        int ncr(int n, int r)
        {
            if (r < 0 || r > n)
                return 0;
            return fac(n) * inv(fac(r)) % mod * inv(fac(n - r)) % mod;
        }
    
        void c_presolve()
        {
            fac__[0] = 1;
            for (int i = 1; i <= 5000; i++)
            {
                fac__[i] = fac__[i - 1] * i % mod;
            }
            for (int i = 0; i <= 5000; i++)
            {
                c__[i][0] = c__[i][i] = 1;
                for (int j = 1; j < i; j++)
                    c__[i][j] = c__[i - 1][j] + c__[i - 1][j - 1], c__[i][j] %= mod;
            }
        }
    
        int __c(int n, int r)
        {
            if (r < 0 || r > n)
                return 0;
            if (n > 5000)
                return ncr(n, r);
            return c__[n][r];
        }
    }
    
    using namespace math_mod;
    
    int solve(int a, int b)
    {
        int ans = 0;
        for (int i = 0; i <= a && i <= b; i++)
        {
            ans += __c(a, i) * __c(b, i) % mod * __fac(i) % mod;
            ans %= mod;
        }
        ans %= mod;
        return ans;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        int a, b, c;
        c_presolve();
        cin >> a >> b >> c;
        int ans = 1;
        ans = (ans * solve(a, b)) % mod;
        ans = (ans * solve(c, b)) % mod;
        ans = (ans * solve(a, c)) % mod;
        cout << ans << endl;
    }
    
  • 相关阅读:
    软工实践个人总结
    实验 7:OpenDaylight 实验——Python 中的 REST API 调用(含选做)
    2020软工实践第二次结对作业
    mocha单元测试简单教程
    实验 6:OpenDaylight 实验——OpenDaylight 及 Postman实现流表下发
    实验 5:OpenFlow 协议分析和 OpenDaylight 安装
    实验 4:Open vSwitch 实验——Mininet 中使用 OVS 命令
    福州大学软件工程实践第一次个人编程作业
    实验 3:Mininet实验 —— 测量路径的损耗率
    实验 2:Mininet 实验——拓扑的命令脚本生成
  • 原文地址:https://www.cnblogs.com/mollnn/p/14484928.html
Copyright © 2011-2022 走看看