Color Gym - 100548F (容斥原理)

思路:先考虑满足不相邻的条件,很容易写出,C(k,m)*k*k^(n-1)。但是这样并不是严格使用了k种颜色的,还包括了使用了1,2,3,....k-1种颜色的,所以,我们需要将其去重。

去重当然是考虑容斥:设使用了前k种颜色为f[k],那么前k-1则为f[k-1],需要注意的是f[k-1]中包含k-2,k-3.....1,同理f[k-2]包括了k-3,k-4....1。

看下表:

f[i-1] f[i-2] f[i-3] f[i-4]  
i-1 没有 没有 没有  
i-2 i-2 没有 没有  
i-3 i-3 i-3 没有  
i-4 i-4 i-4 i-4  

观看上面的表格,如果减去f[i-1]的话,相当于减去整个表格里的内容,一个 i-1, 两个 i-2, 三个 i-3 .....

因为减去了两个i-2,所以需要把i-2加回来一个,所以  + f[i-2] 就行,同样的分析 ,即可解释容斥原理。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e6+7;
const int mod=1e9+7;
ll n,m;
int k;
ll inv[maxn];
ll c[maxn];
ll qpow(int a,int b)
{
    ll ans=1;
    ll  aa=a;
    while(b)
    {
        if(b&1)
        {
            ans=ans*aa%mod;
        }
        aa=aa*aa%mod;
        b>>=1;
    }
    return ans;
}
void init_inv()
{
    for(int i=1;i<maxn;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;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int T;
    cin>>T;
    int Case=0;
    init_inv();
    while(T--)
    {
        scanf("%lld%lld%d",&n,&m,&k);
        ll ans=0;
        cal(k);
        int sign=1;
        for(int i=k;i>=1;i--,sign=-sign)
        {
            ans=(ans+sign*c[i]*i%mod*qpow(i-1,n-1)%mod+mod)%mod;
        }
        cal(m);
        ans=ans*c[k]%mod;
        printf("Case #%d: ",++Case);
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40774175/article/details/82941189
今日推荐