https://vjudge.net/contest/265252#problem/F
给你n朵花,m种颜色,k (1 ≤ n, m ≤ 10^9 , 1 ≤ k ≤ 10^6 , k ≤ n, m)
花是一排,要求相邻花染色不能相同,染色数量刚好等于k,问你染色的方案数
如果用<=k种颜色,那么有k*(k-1)^(n-1) *C(k,1) 种方案 ——A
如果用<=k-1种颜色,那么有(k-1)*(k-2)^(n-1) *C(k,2) 种方案 ——B
如果用<=k-2种颜色,那么有(k-2)*(k-3)^(n-1) *C(k,3) 种方案 ——C
……
A方案包括了用k-1种颜色的要减去B,B中又包括了用k-2种颜色的要加上C
容斥原理!!!!
记得每一次要乘上C(k,i),因为减掉哪种颜色不确定
最后因为在m种颜色里选k种,*C(m,k)
扫描二维码关注公众号,回复:
3955977 查看本文章
又因为m<=1e^9,但是k<=1e^7,
所以用递推
记得容斥原理做的时候,减时先+mod,不然会出负的
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1e9+7;
ll fac[1000005], inv[1000005];
ll quickpow(ll a, ll b)
{
ll ret = 1;
while(b)
{
if(b & 1) ret = (ret * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ret;
}
void init(int p)
{
fac[0] = 1;
for(int i = 1; i <= p; i++)
fac[i]=(fac[i - 1] * i) % mod;
inv[p] = quickpow(fac[p], mod - 2);
for(int i = p - 1; i >= 0; i--)
inv[i] = (inv[i + 1] * (i + 1)) % mod;
}
ll C(ll n, ll m)
{
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
init(1000003);
while(T --)
{
ll n, m, k;
scanf("%lld%lld%lld", &n, &m, &k);
ll ans = quickpow(k - 1, n - 1) * k % mod;
for(int i = 1; i < k - 1; i++)
{
ll sum = quickpow(k - i - 1, n - 1) * (k - i) %mod * C(k , i) % mod;
if(i & 1) ans = (ans - sum + mod) % mod;
else ans = (ans + sum) % mod;
}
for(int i = m - k + 1; i <= m; i++)
{
ans = ans * i % mod;
}
ans = ans * inv[k] % mod;
printf("Case #%d: %lld\n", ++cas, ans);
}
return 0;
}