cf869 C. The Intriguing Obsession(排列组合)

https://codeforces.com/contest/869/C

题意:

有三种颜色的岛屿,数量分别为 \(A,B,C\)

在一些(可能全部或没有)岛屿之间建立了桥梁。一座桥双向连接两个不同的岛。对于任意两个相同颜色的岛甲和乙,要么甲不能到达乙,要么甲要经过至少3座桥才能到达乙

岛两两不同,问造桥方案总数。答案对 998244353 取模

思路:

两种不合法的造桥方式:\(a_i\leftrightarrow a_j\) 和 \(a_i\leftrightarrow b_k\leftrightarrow a_j\) ,其中 \(a_i\) 与 \(a_j\) 为两个同色岛,\(b_k\) 不同色

在 \(A\) 和 \(B\) 之间造桥不会影响在 \(B\) 和 \(C\) 之间造桥,也不会影响在 \(A\) 和 \(C\) 之间造桥

在 \(A\) 和 \(B\) 之间造桥的方案数为 \(f1=\Sigma_{k=0}^{min(A,B)} k!C_A^k C_B^k\) ,总方案数为 \(f1*f2*f3\)

\(A,B,C\le 5000\) ,可以预处理阶乘,快速幂求逆元

#include <bits/stdc++.h>
using namespace std;

const signed N = 5000;
const int p = 998244353;

int ksm(int a, int b)
{
    a %= p;
    int res = 1;
    while(b)
    {
        if(b & 1) res = 1ll*res * a % p;
        a = 1ll*a * a % p;
        b >>= 1;
    }
    return res;
}
int jie[N+10];
void init()
{
    jie[0] = 1;
    for(int i = 1; i <= N; i++) jie[i]=1ll*i*jie[i-1]%p;
}
int inv(int x)
{
    return ksm(x,p-2);
}
int C(int n, int m)
{
    return 1ll*jie[n]*inv(1ll*jie[m]*jie[n-m]%p)%p;
}
int solve(int x, int y)
{
    int ret = 0;
    for(int i = 0; i <= min(x,y); i++)
        ret=(ret+1ll*C(x,i)%p*C(y,i)%p*jie[i]%p)%p;
    return ret;
}
signed main()
{
    init();
    int a, b, c; cin >> a >> b >> c;
    cout << 1ll*solve(a,b)*solve(b,c)%p*solve(a,c)%p;

    return 0;
}

上一篇:【信号与系统】z变换


下一篇:Ext的开发技巧 - 从修改tree.panel的column的默认排序想到的