题目描述
我们有n个空盒子,所以让我们用m种颜色重新着色那些盒子。
盒子排成一行。不允许用相同的颜色给任何相邻的盒子上色。框i和框i + 1表示每隔i,1≤i≤n相邻。
我们还希望n个框的不同颜色的总数恰好是k。
当且仅当至少一个盒子用不同颜色上色时,两种方法才被认为是不同的。
对于恰好这个词,在开始还是不太清楚,学习了一段时间之后,对于此有了自己的理解,恰好需要用至少或者不超过来运用容斥原理进行表示。
分析题目..
1.首先需要进行选择颜色种类C(m, k)种选法
2.我们可以假定当前我们有i种颜色可以使用,对当前的j位置进行上***r> 想一下,我们可以知道对于j位置来说,它只会对旁边两个位置产生影响,所以当前j位置有i种选法,那么其它位置就有i-1种选法,那么就是i(i-1)^(n-1);
3.由题目的描述中的恰好在此题目中,需要理解为不超过k种颜色的容斥原理进行求解。
由上面的三点我们可以得到答案
ans = C(m,k)(C(k,k)k(k-1)^(n-1) - C(k,k-1)(k-i)(k-2)^(n-1)) + ........
**求解C(m,k),由于m是属于(1,1e9)那么就不能用预处理数组进行求解,可以利用自己喜欢的方式进行求解~~
#include<bits/stdc++.h>
#define ll long long
#define pr printf
#define sc scanf
using namespace std;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
ll fact[maxn],infact[maxn];
ll qpow(ll a, ll b){
ll ans = 1;
while(b){
if(b & 1)ans = ans*a%mod;
b >>= 1;
a = a*a%mod;
}
return ans;
}
ll inv(ll a){
return qpow(a,mod-2)%mod;
}
ll C(ll a, ll b){
if(b > a || a < 0 || b < 0)return 0;
if(b == 0 || b == a)return 1;
return fact[a]*infact[b]%mod*infact[a-b]%mod;
}
void init() {
fact[0] = 1;
for (int i = 1; i < maxn; i++) {
fact[i] = fact[i - 1] * i % mod;
}
infact[maxn - 1] = qpow(fact[maxn - 1], mod - 2);
for (int i = maxn - 2; i >= 0; i--) {
infact[i] = infact[i + 1] * (i + 1) % mod;
}
}
int main() {
init();
int T;
sc("%d", &T);
while (T--) {
ll n, m, k, ans = 0;
sc("%lld%lld%lld", &n, &m, &k);
for (int i = 0, cur = 1; i < k; i++, cur = -cur)
ans = (ans + cur * C(k, k - i) * (k - i) % mod * qpow(k - i - 1, n - 1) % mod + mod) % mod;
for (int i = 0; i < k; i++)
ans = ans * (m - i) % mod * inv(k - i) % mod;
cout << ans << endl;
}
return 0;
}
京公网安备 11010502036488号