题意:n个球有m种颜色可选,使用k种不同的颜色,求方案数;
思路:Cm[k]表示m中选k,方案数为Cm[k]*(k*(k-1)^(n-1)-sigma(p*(p-1)^(n-1))(1<=p<k));
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MOD 1000000007 int t,n,m,k; long long ck[5000100],cm[5000010]; long long inv[5000100]; long long ans; void init(){ //预处理逆元 inv[1]=1; for(int i=2;i<=1000100;i++){ inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD; } } long long pow(long long a,long long b){ //快速幂 long long res=1,temp=a; if(b==0) return 1; if(b==1) return a; while(b){ if(b&1) res=res*temp%MOD; temp=temp*temp%MOD; b/=2; } return res; } void combine(){ //组合数 ck[0]=cm[0]=1; for(int i=1;i<=k;i++){ ck[i]=ck[i-1]%MOD*(k-i+1)%MOD*inv[i]%MOD; cm[i]=cm[i-1]%MOD*(m-i+1)%MOD*inv[i]%MOD; } } int main() { int i,j,cas,flag; init(); scanf("%d",&t); for(cas=1;cas<=t;cas++){ scanf("%d%d%d",&n,&m,&k); printf("Case #%d: ",cas); combine(); ans=0;flag=1; for(i=k;i>=1;i--){ if(flag){ ans=((ans+ck[i]*i%MOD*pow(i-1,n-1)%MOD)%MOD+MOD)%MOD;//取模不准确也会wa } else{ ans=((ans-ck[i]*i%MOD*pow(i-1,n-1)%MOD)%MOD+MOD)%MOD; } flag=1-flag; } ans=ans*cm[k]%MOD; printf("%lld\n",ans); } return 0; }
时间: 2024-10-09 22:43:23