uvalive7040 / cf gym 100548 Color(2014西安區域賽F題)
阿新 • • 發佈:2019-01-09
Source
題意
n個格子排成一行,有m種顏色,問用恰好k種顏色進行染色,使得相鄰格子顏色不同的方案數。
分析
在網上看到的幾篇解題報告好像沒講清楚為什麼是容斥(反正我沒看懂。。),所以我也寫一篇。
首先,我們可以從m個顏色中取出k個,即
接著容易想到
假設選出的k種顏色標號為1,2,3,…, k,那麼記 S|
程式碼
/*************************************************************************
> File Name: uvalive_7040.cpp
> Author: james47
> Mail:
> Created Time: Sat Aug 8 08:47:40 2015
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int mod = (int)1e9+7;
int pow_mod(int a, int exp){
int ret = 1;
while(exp){
if (exp&1) ret = (long long)ret * a % mod;
a = (long long)a * a % mod;
exp >>= 1;
}
return ret;
}
int c[(int)1e6+100];
int inv[(int)1e6+100];
int cal(int n, int m, int k){
if (k == 1 && n == 1) return m;
if (k == 1 && n > 1) return 0;
int ret = 1, lim = min(k, m - k);
for (int i = 1; i <= lim; i++) ret = (long long)ret * (m-i+1) % mod * inv[i] % mod;
c[0] = 1;
for (int i = 1; i <= k; i++) c[i] = (long long)c[i-1] * (k-i+1) % mod * inv[i] % mod;
int tmp, tot = (long long)k * pow_mod(k-1, n-1) % mod;
for (int i = 1; i+1 < k; i++){
tmp = (long long)c[i] * (k-i) % mod * pow_mod(k-i-1, n-1) % mod;
if (i&1){
tot = tot - tmp;
if (tot < 0) tot += mod;
}
else{
tot = tot + tmp;
if (tot >= mod) tot -= mod;
}
}
ret = (long long)ret * tot % mod;
return ret;
}
void init(){
inv[1] = 1;
for (int i = 2; i <= 1000000; i++){
inv[i] = (long long)(mod - mod/i) * inv[mod % i] % mod;
}
}
int T, n, m, k;
int main()
{
init();
scanf("%d", &T); int cas = 0;
while(T--){
scanf("%d %d %d", &n, &m, &k);
printf("Case #%d: %d\n", ++cas, cal(n, m, k));
}
return 0;
}