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)k−i∗C(k,i)∗(i)∗(i−1)n−1 (容斥也忘记了,留坑).
#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");
}