UVALive-7040-Color(容斥原理)

链接:

https://vjudge.net/problem/UVALive-7040

题意:

Recently, Mr. Big recieved n owers from his fans. He wants to recolor those owers with m colors. The
owers are put in a line. It is not allowed to color any adjacent owers with the same color. Flowers i and
i + 1 are said to be adjacent for every i, 1 ≤ i < n. Mr. Big also wants the total number of different
colors of the n owers being exactly k.
Two ways are considered different if and only if there is at least one ower being colored with different
colors

思路:

先C(n, k),考虑k个有(k * (k-1)^{n-1})。减掉少一个不选的有((k-1)*(k-2)^{n-1})
其中多减掉了两个不选的要加上。
最后:(sum_{i=1}^{k-1}(-1)^i*C_k^{k-i}*(k-i)*(k-i-1)^{n-1})

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
#include<vector>

using namespace std;
typedef long long LL;
const int INF = 1e9;

const int MAXN = 1e6+10;
const int MOD = 1e9+7;

LL n, m, k;
LL F[MAXN], Inv[MAXN], Finv[MAXN];

LL Pow(LL a, LL b)
{
    LL res = 1;
    while(b>0)
    {
        if (b&1)
            res = res*a%MOD;
        a = a*a%MOD;
        b >>= 1;
    }
    return res;
}

LL GetInv(int a)
{
    return Pow(a, MOD-2);
}

void Init()
{
    Inv[1] = 1;
    for (int i = 2;i < MAXN;i++)
        Inv[i] = (MOD-MOD/i)*1LL*Inv[MOD%i]%MOD;
    F[0] = Finv[0] = 1;
    for (int i = 1;i < MAXN;i++)
    {
        F[i] = F[i-1]*1LL*i%MOD;
        Finv[i] = Finv[i-1]*1LL*Inv[i]%MOD;
    }
}

LL Comb(int n, int m)
{
    if (m < 0 || m > n)
        return 0;
    return F[n]*1LL*Finv[m]%MOD*Finv[n-m]%MOD;
}

int main()
{
    Init();
    int t, cnt = 0;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%lld%lld%lld", &n, &m, &k);
        LL res = 1LL*k*Pow(k-1, n-1)%MOD;
        int flag = -1;
        for (int i = 1;i <= k-1;i++)
        {
            res = (res+1LL*flag*Comb(k, k-i)*(k-i)%MOD*Pow(k-i-1, n-1)%MOD)%MOD;
            flag = -flag;
        }
        LL temp = Finv[k];
        for (int i = 1;i <= k;i++)
        {
            temp = 1LL*temp*(m-k+i)%MOD;
        }
        res = ((1LL*res*temp)%MOD+MOD)%MOD;
        printf("Case #%d: %lld
", ++cnt, res);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/YDDDD/p/11809151.html