Codeforces Gym 100548F Color (组合数+容斥)

来源:互联网 发布:自助点餐软件 编辑:程序博客网 时间:2024/05/16 14:52

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 longint 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);    }}


0 0
原创粉丝点击