Codeforces Gym 100548F Color (組合數+容斥)

_TCgogogo_發表於2015-09-12

2014西安區域賽的題,當時弱狗一條,2題gg

Color

Description

Recently, Mr. Bigrecieved n flowers from his fans. He wants to recolor those flowerswith m colors. The flowers are put in a line. It is not allowed tocolor any adjacent flowers with the same color. Flowers i and i + 1are said to be adjacent for every i, 1 ≤ i < n. Mr. Big alsowants the total number of different colors of the n flowers beingexactly k.

Two ways areconsidered different if and only if there is at least one flowerbeing colored

with differentcolors.


Input

The first line ofthe input gives the number of test cases, T. T test cases follow. Tis about 300 and in most cases k is relatively small.

For each test case,there will be one line, which contains three integers n, m, k (1 ≤n, m ≤ 10^9, 1 ≤ k ≤ 10^6, k ≤ n, m).


Output

For each test case,output one line containing “Case #x: y”, where x is the test casenumber (starting from 1) and y is the number of ways of differentcoloring methods modulo 10^9 + 7.


Samples

Sample Input

Sample Output

2

3 2 2

3 2 1

Case #1: 2

Case #2: 0


題目連結:http://codeforces.com/gym/100548/attachments


題目大意:直線上給n個物品染色,一共有m種顏色,求恰好用了k種顏色的染色方案數


題目分析:首先從m種顏色種選取k種顏色的方案為C(m,k),對於不超過的k種顏色的方案數很好求,為k*(k - 1)^(n - 1),第一個物品有k種選擇,之後的n-1個物品因為不能和前面的相同,故都只有n-1種可能,但是題目要求的是恰好為k種的方案數,因此要容斥一下,容斥可以這樣理解,假設不超過i種的方案數為F[i],那麼其中包括了不超過i-1種的,不超過i-1種的裡面又包含了不超過i-2種的,以此類推得到ans = F[k] - (F[k - 1] - (F[k - 2] - (... - (F[3] - F[2])))) = F[k] - F[k - 1] + F[k - 2] - ... + (-1)^(k - i)F[i]

因此最後答案為C(m,k)(Σ(-1)^(k - i)F[i]),其中F[i] = C(k,i)i*(i-1)^(n-1)

#include <cstdio>
#define ll long long
int const MOD = 1e9 + 7;
int const MAX = 1e6 + 5;
ll n, m, k, c[MAX], inv[MAX];

ll qpow(ll x, ll n)
{
    ll res = 1;
    while(n)
    {
        if(n & 1)
            res = (res * x) % MOD;
        x = (x * x) % MOD;
        n >>= 1;
    }
    return res;
}

void Init_inv()
{
    for(int i = 1; i < MAX; i++)
        inv[i] = qpow(i, MOD - 2);
}

void cal(ll n)
{
    c[0] = 1;
    for(int i = 1; i <= k; i++)
        c[i] = ((c[i - 1] * (n - i + 1) % MOD) * inv[i] % MOD) % MOD;
}

int main()
{
    Init_inv();
    int T;
    scanf("%d", &T);
    for(int ca = 1; ca <= T; ca++)
    {
        scanf("%I64d %I64d %I64d", &n, &m, &k);
        cal(k);
        ll ans = 0;
        int sign = 1;
        for(int i = k; i >= 1; i--, sign = -sign)
            ans = (ans % MOD + (sign * i * qpow(i - 1, n - 1)) % MOD * c[i] % MOD + MOD) % MOD;
        cal(m);
        printf("Case #%d: %I64d\n", ca, (ans % MOD * c[k] % MOD) % MOD);
    }
}


相關文章