2014-2015 ACM-ICPC, Asia Xian Regional Contest F Color

2014-2015 ACM-ICPC, Asia Xian Regional Contest F Color

题意

n个格子排成一行,有m种颜色,问用恰好k种颜色进行染色,使得相邻格子颜色不同的方案数。

思路

组合计数+容斥(奇加偶减)

公式为 ∑ i = 1 k ( − 1 ) k − i ∗ C ( k , i ) ∗ ( i ) ∗ ( i − 1 ) n − 1 \sum_{i=1}^k(-1)^{k-i}*C(k,i)*(i)*(i-1)^{n-1} i=1k(1)kiC(k,i)(i)(i1)n1 (容斥也忘记了,留坑).

代码

#include
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e9+7;
ll jc[maxn],jcinv[maxn];
int C(int n,int m){
    return jc[n]*jcinv[m]%mod*jcinv[n-m]%mod;
}
ll ksm(long long a,int b){
    long long c=1;
    for(;b;b>>=1){
        if(b&1) c=c*a%mod;
        a=a*a%mod;
    }
    return c;
}
void init(){
    jc[0]=1;jcinv[0]=1;
    for(int i=1;i<=1000000;i++){
        jc[i]=jc[i-1]*i%mod;
        jcinv[i]=ksm(jc[i],mod-2);
    }
}
ll f(ll m,ll k){
    if(k>m) return 0;
    ll ans=1;
    for(int i=1;i<=k;i++){
        ans=ans*(m-i+1)%mod*ksm(i,mod-2)%mod;
    }
    return ans;
}
int main(){
    // printf("%d\n",0%2);
    // printf("%lld %lld\n",f(5,1),f(5,3));
    init();
    // printf("%d")
    int _;scanf("%d",&_);
    int id=0;
    
    while(_--){
        int n,m,k;scanf("%d%d%d",&n,&m,&k);
        ll ans=0;
        // printf("ans=%lld\n",ans);
        ll flag=1;
        for(int i=1;i<=k;i++){
            // printf("%d\n",C(k,i));
            ll tmp=i*ksm(i-1,n-1)%mod;
            // printf("tmp=%lld\n",tmp);
            if((k-i)%2==0) ans=((ans+tmp*C(k,i))%mod+mod)%mod;
            else ans=((ans-tmp*C(k,i))%mod+mod)%mod;
            // flag*=-1;
        }
        printf("Case #%d: %lld\n",++id,ans*f(m,k)%mod);
    }
    //system("pause");
}

你可能感兴趣的:(数论,组合计数,容斥)