链接:
https://vjudge.net/problem/UVALive-7040
题意:
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
思路:
先C(n, k),考虑k个有\(k * (k-1)^{n-1}\)。减掉少一个不选的有\((k-1)*(k-2)^{n-1}\)。
其中多减掉了两个不选的要加上。
最后:\(\sum_{i=1}^{k-1}(-1)^i*C_k^{k-i}*(k-i)*(k-i-1)^{n-1}\)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
typedef long long LL;
const int INF = 1e9;
const int MAXN = 1e6+10;
const int MOD = 1e9+7;
LL n, m, k;
LL F[MAXN], Inv[MAXN], Finv[MAXN];
LL Pow(LL a, LL b)
{
LL res = 1;
while(b>0)
{
if (b&1)
res = res*a%MOD;
a = a*a%MOD;
b >>= 1;
}
return res;
}
LL GetInv(int a)
{
return Pow(a, MOD-2);
}
void Init()
{
Inv[1] = 1;
for (int i = 2;i < MAXN;i++)
Inv[i] = (MOD-MOD/i)*1LL*Inv[MOD%i]%MOD;
F[0] = Finv[0] = 1;
for (int i = 1;i < MAXN;i++)
{
F[i] = F[i-1]*1LL*i%MOD;
Finv[i] = Finv[i-1]*1LL*Inv[i]%MOD;
}
}
LL Comb(int n, int m)
{
if (m < 0 || m > n)
return 0;
return F[n]*1LL*Finv[m]%MOD*Finv[n-m]%MOD;
}
int main()
{
Init();
int t, cnt = 0;
scanf("%d", &t);
while(t--)
{
scanf("%lld%lld%lld", &n, &m, &k);
LL res = 1LL*k*Pow(k-1, n-1)%MOD;
int flag = -1;
for (int i = 1;i <= k-1;i++)
{
res = (res+1LL*flag*Comb(k, k-i)*(k-i)%MOD*Pow(k-i-1, n-1)%MOD)%MOD;
flag = -flag;
}
LL temp = Finv[k];
for (int i = 1;i <= k;i++)
{
temp = 1LL*temp*(m-k+i)%MOD;
}
res = ((1LL*res*temp)%MOD+MOD)%MOD;
printf("Case #%d: %lld\n", ++cnt, res);
}
return 0;
}