【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;
}
相關文章
相關標籤/搜索