2017多校第8场 HDU 6143 Killer Names 容斥,组合计数

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6143

题意:m种颜色需要为两段长度为n的格子染色,且这两段之间不能出现相同的颜色,问总共有多少种情况。

解法:枚举要为这两段分配的颜色数目分别为 i,j ,则在第一段总共有 C(m,i) 种选取方案,在第二段总共有 C(mi,j) 种选取方案。而在每段内部,我们设 F(n,x) 为长度为 n 的格子使用 x 种颜色(等于 x )染色的方案数。则根据容斥原理 F(n,x)=x^n−C(x,1)*(x1)^n+C(x,2)*(x2)^nC(x,3)*(x3)^n+...于是最终的结果便是所有 C(m,i)F(n,i)×C(mi,j)F(n,j) 之和。

补充:这个题还可以利用斯特林数来做

 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9+7;
LL n,m,C[2005][2005],cal[2005];
LL qsm(LL a, LL n){
    LL ret = 1;
    while(n){
        if(n&1) ret=ret*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ret;
}
void pre_deal()
{
    C[0][0]=1;
    for(int i=1; i<=2001; i++){
        C[i][0]=1;
        for(int j=1; j<=i; j++){
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
    }
}
int main()
{
    pre_deal();
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld%lld", &n,&m);
        LL ans=0;
        for(LL i=1; i<=n; i++){
            cal[i]=qsm(i,n);
            for(LL j=1;j<i;j++){
                cal[i]-=C[i][j]*cal[j]%mod;
                cal[i]=(cal[i]+mod)%mod;
            }
        }
        for(LL i=1; i<=n; i++){
            if(i>=m) break;
            for(LL j=1; j<=n; j++){
                if(j>m-i) break;
                ans += C[m][i]*cal[i]%mod*C[m-i][j]%mod*cal[j]%mod;
                ans %= mod;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

 

posted @ 2017-08-19 21:38  zxycoder  阅读(181)  评论(0编辑  收藏  举报