Codeforces Round #439 C. The Intriguing Obsession

题意:给你三种不同颜色的点,每种若干(小于5000),在这些点中连线,要求同色的点的最短路大于等于3或者不连通,求有多少种连法。

Examples
Input
1 1 1
Output
8
Input
1 2 2
Output
63
Input
1 3 5
Output
3264
Input
6 2 9
Output
813023575

思路:从第一个样例来看点与点之间是可以不连通的,而且题目要求同色点的最短路大于等于3,也就是说两个同色的点不能连到同一点
    上去。仔细想想,每个点是不影响整体的合法性的,也就是说如果整体是合法的,去掉其中一个点以及它连的线是合法的,加上一
    个合法连线的点也是合法的。所以我们可以算出每种颜色互相连的方案数然后乘起来就行了。
    这里算方案数的时候,是取两种颜色的点的个数x,y的最小值mi,然后i从0到mi,ans+=C[x][i]*C[y][i]*阶乘(i)
    相当于是一个排列组合吧23333.

代码:
#include<iostream>
#include<algorithm>
using namespace std;

const int mod=998244353;
const int maxn=5005;
int C[maxn][maxn],f[maxn],a,b,c;

void init(){
    f[0]=1;
    for(int i=1;i<=maxn;i++){
        f[i]=1LL*f[i-1]*i%mod;
        C[i][0]=1;
    }
    C[0][0]=1;
    for(int i=1;i<=maxn;i++){
        C[i][i]=1;
        for(int j=1;j<i;j++){
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
    }
}

int solve(int x,int y){
    int mi=min(x,y),ans=0;
    for(int i=0;i<=mi;i++){
        ans=(ans+((1LL*C[x][i]*C[y][i])%mod*f[i])%mod)%mod;
    }
    return ans;
}
int main(){
    init();
    cin>>a>>b>>c;
    int ans1=solve(a,b),ans2=solve(a,c),ans3=solve(b,c);
    int sum=(((1LL*ans1*ans2)%mod)*ans3)%mod;
    cout<<sum<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/ljy08163268/p/7634552.html