【UVALive - 7040】:Color 【容斥原理】

题目:

UVALive - 7040 :Color

题意:

大致是一共有 M 中颜色,你需要从中选 K 种给 N 个物品染色,要求相邻的不能染一样的颜色,并且每种颜色都要用上,求染色的方案数

笔记:

学习自:容斥原理详解

容斥公式:

先看这个问题:K 种颜色给 N 个物品染色,要求相邻的不能染一样的颜色的方案数,答案就是:k*pow(k-1,n-1),此时算的是小于等于 k 个颜色的总方案数;容斥原理的套路就是考虑其逆问题:至少有一种颜色不用;设 A1 为不用第一种颜色的方案数,A2 为不用第二种颜色的方案数......Ak 为不用第 k 种颜色的的集合,逆问题的方案数就是 Ai 的并集,这个就可以通过容斥公式计算;那么最后的答案就是: (总方案数 - 逆问题的方案数) * m 种颜色中选 k 种颜色的方案数

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int mod = 1e9+7;
const int maxn = 1e6+16;
int inv[maxn],T,n,m,k;
LL qpow(LL a,LL x){
    LL res = 1;
    while(x){
        if(x&1) res = res*a%mod;
        a = a*a%mod;
        x >>= 1;
    }
    return res;
}
inline LL cal(int n,int k){
    return k*qpow(k-1,n-1)%mod;
}
void init(){                                //预处理逆元
    inv[1] = 1;
    for(int i = 2;i < maxn; ++i) 
        inv[i] = 1ll*(mod-mod/i)*inv[mod%i]%mod;
}
LL solve(int n,int k){                      //容斥公式算逆问题的方案数
    LL res = 0; LL v = 1;
    for(int i = 1;i <= k-2; ++i){
        v = v*(k-i+1)%mod*inv[i]%mod;
        if(i&1) res += v*cal(n,k-i);
        else res -= v*cal(n,k-i);
        res = (res%mod+mod)%mod;
    }
    return res;
}
LL C(int m,int k){                          //递推求组合数
    LL res = 1;
    for(int i = 1;i <= k; ++i)
        res = res*(m-i+1)%mod*inv[i]%mod;
    return res;
}
int main(){
    scanf("%d",&T); init();
    for(int Case = 1;Case <= T; ++Case){
        scanf("%d %d %d",&n,&m,&k);
        printf("Case #%d: %d\n",Case,(int)(C(m,k)*(cal(n,k)-solve(n,k)+mod)%mod));
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值