题目链接
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;
}