zoukankan      html  css  js  c++  java
  • CF869C The Intriguing Obsession(排列组合)

    链接:https://ac.nowcoder.com/acm/contest/21791/E
    来源:牛客网

    题目描述
    岛上有三种颜色的岛屿,分别是红色、蓝色和紫色。岛群分别由

    a
    ,
    b
    a,b和

    c
    c个不同的岛组成。

    在一些(可能全部或没有)岛屿之间建立了桥梁。一座桥双向连接两个不同的岛,长度为

    1
    1。对于任意两个相同颜色的岛,要么不能通过桥相互到达,要么它们之间的最短距离至少为

    3
    3。

    Fire Sisters 已准备好迎接未知,但他们也想测试您的勇气。你来这里是为了找出在约束条件下建造所有桥梁的不同方法的数量,并给出模

    998244353
    998244353 的答案。如果存在一对岛,它们之间有一座桥,但另一种没有桥,则两种方法被认为是不同的。
    输入描述:
    输入包含三个空格分隔的整数

    a
    ,
    b
    ,
    c

    1

    a
    ,
    b
    ,
    c

    5000

    a,b,c(1≤a,b,c≤5000),分别表示岛群中红色、蓝色和紫色的岛数。
    输出描述:
    输出一行包含一个整数,表示构建桥梁的不同方法的数量,模

    998244353
    998244353。
    示例1
    输入

    复制
    1 1 1
    输出

    复制
    8
    说明

    在这个例子中,有 3 座可能建造的桥,并且没有任何桥的设置违反限制。因此答案是

    2
    3

    8
    2
    3
    =8。
    示例2
    输入

    复制
    1 2 2
    输出

    复制
    63
    说明

    下图中,上方两个是有效结构,而下方两个是无效的。

    示例3
    输入

    复制
    1 3 5
    输出

    复制
    3264
    示例4
    输入

    复制
    6 2 9
    输出

    复制
    813023575

    根据题意,两个同色的岛之间的最短距离为3等价于两个同色的岛屿之间不能有边相连,同时两个同色的岛屿也不能同时连接到同一个岛。这样就好办了,对于每两种颜色可以计算这两种颜色的岛之间的连边的方案数,然后由乘法原理把这三种方案数乘起来即可。对于A和B这两种颜色,如果他们之间的岛屿连边一定是一个类似二分图的形式,只需要枚举连的边的数量然后用组合数计算方案即可。形式化地来说,对于输入的a和b,若这两种颜色的岛屿的连边数为i,那么方案数就是(C_{a}^{i} imes C_{b}^{i} imes i!),阶乘的话也很好理解。

    
    // Created on 解志国的iPad.
    
    #include <iostream>
    #define ll long long
    #define LL long long
    #define mod 998244353
    #define p 998244353
    using namespace std;
    ll a, b, c, ans = 1;
    ll F(ll x) {
        ll ans = 1;
        for(int i = 1; i <= x; i++) {
            ans = ans * i % mod;
        }
        return ans;
    }
    const int maxn=1000005;
    void extend_gcd(LL a,LL b,LL &x,LL &y){
        if(b==0){
            x=1,y=0;
            return;
        }
        extend_gcd(b,a%b,y,x);
        y-=a/b*x;
    }
    
    LL inv[maxn+10];
    LL f[maxn+10];
    void init(){//阶乘及其逆元打表
        f[0]=1;
        for(int i=1;i<=maxn;i++){
            f[i]=f[i-1]*i%p;
        }
    
        LL x,y;
        extend_gcd(f[maxn],p,x,y);//先求出f[N]的逆元,再循环求出f[1~N-1]的逆元
        inv[maxn]=(x%p+p)%p;
        for(int i=maxn-1;i>=1;i--){
            inv[i]=inv[i+1]*(i+1)%p;
        }
    }
    
    LL C(LL n,LL m){
        if(n==m||m==0)return 1;
        return (f[n]*inv[m]%p*inv[n-m]%p)%p;
    }
    int main() {
        init();
        cin >> a >> b >> c;
        ll ta = 0, tb = 0, tc = 0;
        for(ll i = 0; i <= min(a, b); i++) {
            ta = (ta + (C(a, i) * C(b, i) % mod * F(i) % mod) % mod) % mod;
        }
        for(ll i = 0; i <= min(b, c); i++) {
            tb = (tb + (C(b, i) * C(c, i) % mod * F(i) % mod) % mod) % mod;
        }
        for(ll i = 0; i <= min(a, c); i++) {
            tc = (tc + (C(a, i) * C(c, i) % mod * F(i) % mod) % mod) % mod;
        }
        cout << ta * tb % mod * tc % mod;
        return 0;
    }
    
    
  • 相关阅读:
    三层架构及生活实例
    初识ADO.NET
    remoting与socket、web service的比较及实例
    ERP与MES
    25人赛跑问题-得出前三名
    WPF导学目录
    心目中的职业初规划
    应用服务器
    2015广深骑行记
    ASP.NET的几个试题(《C#与.NET程序员面试宝典》)
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15439793.html
Copyright © 2011-2022 走看看