传送门
英文题目:
Recently, Mr. Big recieved n owers from his fans. He wants to recolor those owers with m colors. The
owers are put in a line. It is not allowed to color any adjacent owers with the same color. Flowers i and
i + 1 are said to be adjacent for every i, 1 ≤ i < n. Mr. Big also wants the total number of different
colors of the n owers being exactly k.
Two ways are considered different if and only if there is at least one ower being colored with different
colors.
插图:
题目大意:
首先有T组数据,每组数据有 3 个数 n, m, k,分别代表一共有 n 个方格,m种颜色,而我们要 恰好(注意是恰好) 使用 k 中颜色对这些方格进行涂色,并且保证的是每两个相邻的方格的颜色必须是不一样的。
解题思路:
首先拿过这个题来 不要急着就是说一眼就做出来,所以我们先对它分析一下,我们要从 m 种颜色中选出 k 个进行涂色 所以用的方法数就是 C(m,k),然后对这 n 个方格涂色,第一个 有 k 种选择, 而后边的 n-1 个方格中只有 k-1 种选择,所以 就有公式
My Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MOD = 1e9+7;
const int MAXN = 1e6+5;
typedef long long LL;
LL Scan()///输入外挂
{
LL res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
void Out(LL a)///输出外挂
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
///快速幂
LL quick_mod(LL a, LL b)
{
LL ans = 1;
while(b)
{
if(b & 1)
ans = ans*a%MOD;
b>>=1;
a = a*a%MOD;
}
return ans;
}
///求逆元
void Exgcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
LL x1, y1;
Exgcd(b, a%b, x1, y1);
x = y1;
y = x1 - (a/b)*y1;
}
LL Inv[MAXN];///放逆元的数组
///得到逆元
void Get_Inv()
{
Inv[1] = 1;
for(int i=2; i<MAXN; i++)
{
LL y;
Exgcd(i, MOD, Inv[i], y);
Inv[i] = (Inv[i]%MOD+MOD)%MOD;
}
}
/** 得到组合数,通过递推公式 C(m,i) = C(m,i-1)*(m-i+1)/i; **/
LL cm[MAXN], ck[MAXN];///分别是m的组合数 和 k 的组合数
LL n, m, k;
void Get_Fac()
{
cm[0] = ck[0] = 1;
for(int i=1; i<=k; i++)
{
cm[i] = (cm[i-1]%MOD * (m-i+1)%MOD * Inv[i]%MOD) % MOD;
ck[i] = (ck[i-1]%MOD * (k-i+1)%MOD * Inv[i]%MOD) % MOD;
}
}
/** 11 1000000000 1000000000 1000000 **/
int main()
{
Get_Inv();
int T;
T = Scan();
for(int cas=1; cas<=T; cas++)
{
n = Scan();
m = Scan();
k = Scan();
Get_Fac();
LL ret = 1;
LL ans = 0;
for(LL i=k; i>=1; i--)
{
ans = (ans+ret*i*ck[i]%MOD*quick_mod(i-1,n-1)%MOD+MOD)%MOD;
ret = -ret;
//cout<<ans<<" ";
}
ans = ans * cm[k] % MOD;
printf("Case #%d: %lld\n",cas,ans);
}
return 0;
}