NC13884 Paint Box

题目链接

https://ac.nowcoder.com/acm/problem/13884

题意

\(n\)个盒子, \(m\)种颜色, 相邻盒子不同色,问恰好使用k种颜色的方案数,答案 对\(1e9+7\)取模

思路

恰好的问题, 一般转换成至少或者不超过, 然后用容斥去做
不超过\(k\)的方案数为\(k∗(k−1)^{n-1}\)
容斥一下
即减去用不超过\(k−1\)种颜色的方案数 这有\(C(k, k - 1)\)
加上不超过\(k-2\)种颜色的方案数
…………
直到\(1\)种颜色为止
最后从\(m\)种颜色中选出\(k\)种, 答案乘以 \(C(m, k)\), \(m\) 较大, 但是 \(k\) 不大 可以化成组合数公式线性求。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 50;
const int mod = 1e9 + 7;
ll fac[maxn];
ll qpow(ll a,ll b){
    ll ans = 1;a %= mod;
    for(ll i = b;i;i >>= 1,a = a * a % mod)
        if(i & 1) ans = ans * a % mod;
    return ans % mod;
}
ll C(ll n,ll m){
    if(m > n || m < 0) return 0;
    ll s1 = fac[n],s2 = fac[n - m] * fac[m] %mod;
    return s1 * qpow(s2,mod - 2) % mod;
}
void init(){
    fac[0] = 1;
    for(int i = 1;i < maxn;i++)
    fac[i] = fac[i-1] * i % mod;
}
ll inv(ll x){
    return qpow(x, mod - 2) % mod;
}
int main()
{
    std::ios::sync_with_stdio(false);
    init();
    int t;
    cin >> t;
    while(t--){
        ll n, m, k;
        cin >> n >> m >> k;
        ll ans = 0;
        ll cnt = 1;
        for(int i = 0;i < k;i++){
            ans += cnt * (k - i) * qpow(k - i - 1, n - 1) % mod * C(k, k - i) % mod;
            ans = (ans + mod) % mod;
            cnt *= -1;
        }
        for(int i = 0;i < k;i++){
            ans = ans * (m - i) % mod * inv(k - i) % mod;
        }
        cout << ans << endl;
    }
    return 0;
}

posted @ 2020-11-21 00:12  Carered  阅读(101)  评论(0编辑  收藏  举报