逆元 适用 mod 为素数
C(n, m) 函数适用 n, m 在 1kw 以下时
n 过大时可暴力 均过大用 lucas定理
小于等于 k 种颜色 k * (k - 1) ^ (n - 1)
减去 (k - 1) * (k - 2) ^ (n - 1) * (不选的 k 种可能颜色)
有重复减去的部分
选 i 种颜色的情况数为 C(k, i)
#include <bits/stdc++.h>
#define ll long long
const long long mod = 1e9 + 7;
using namespace std;
ll Pow(ll a, ll b) // 快速幂
{
ll ans = 1;
ll t = a;
while (b != 0)
{
if (b & 1)
ans = (ans * t) % mod;
t = (t * t) % mod;
b >>= 1;
}
return ans;
}
/// C(n, m) 组合数函数
ll fac[1000005], inv[1000005], num[1000005];
void init(int p)
{
fac[0] = 1;
for (int i = 1; i <= p; i++)
fac[i] = fac[i - 1] * i % mod;
inv[p] = Pow(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()
{
init(1000004); ///
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++)
{
ll n, m, k;
scanf("%lld %lld %lld", &n, &m, &k);
ll ans = 0;
ll t = 1;
for (int i = k; i > 0; i--, t = (-1) * t) /// 容斥
ans = (ans + t * C(k, i) % mod * i % mod * Pow(i - 1, n - 1) % mod + mod) % mod;
// ans *= C(m , k) m太大, 暴力加逆元
for (int i = m; i >= m - k + 1; i--)
ans = ans * i % mod;
ans = ans * inv[k] % mod;
printf("Case #%d: %lld\n", cas, ans);
}
return 0;
}
[容斥 组合数学] 求序列不相邻恰好k种颜色着色 Gym - 100548F
猜你喜欢
转载自blog.csdn.net/ummmmm/article/details/83386358
今日推荐
周排行