【UVALive-7040F】Color

题目大意:给定一个长度为 N 的序列,现有 M 种颜色,选出一些颜色对这个序列进行染色,要求相邻元素颜色不相同。求最终序列刚好有 K 种不一样颜色的染色方案数,结果对1e9+7取模。ios

题解:二项式反演c++

代码以下spa

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const LL mod = 1e9 + 7;
const int maxn = 1e6 + 10;

LL fpow(LL a, LL b) {
    LL ret = 1 % mod;
    for (; b; b >>= 1, a = a * a % mod) {
        if (b & 1) {
            ret = ret * a % mod;
        }
    }
    return ret;
}

LL fac[maxn], ifac[maxn];

void prework() {
    int n = 1e6;
    fac[0] = fac[1] = 1;
    for (int i = 2; i <= n; i++) {
        fac[i] = fac[i - 1] * i % mod;
    }
    ifac[n] = fpow(fac[n], mod - 2);
    for (int i = n - 1; i >= 0; i--) {
        ifac[i] = ifac[i + 1] * (i + 1) % mod;
    }
}
inline LL comb1(int x, int y) {
    if (y > x) {
        return 0;
    }
    return fac[x] * ifac[x - y] % mod * ifac[y] % mod;
}
inline LL comb2(int x, int y) {
    if (y > x) {
        return 0;
    }
    LL ret = 1;
    for (int i = x; i >= x - y + 1; i--) {
        ret = ret * i % mod;
    }
    return ret * ifac[y] % mod;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    prework();
    int T, kase = 0;
    cin >> T;
    while (T--) {
        int n, m, K;
        cin >> n >> m >> K;
        auto f = [&](int x) {
            LL ret = x;
            return ret * fpow(x - 1, n - 1) % mod;
        };
        LL ans = 0;
        if (K == 1) {
            ans = (n == 1) ? 1 : 0;
        } else {
            for (int i = 1; i <= K; i++) {
                if ((K - i) & 1) {
                    ans = (ans - comb1(K, i) * f(i) % mod + mod) % mod;
                } else {
                    ans = (ans + comb1(K, i) * f(i) % mod) % mod;
                }
            }   
        }
        cout << "Case #" << ++kase << ": " << ans * comb2(m, K) % mod << endl;
    }
    return 0;
}
相关文章
相关标签/搜索