题意,有m种颜色,给2n个位置染色,使左边n个和右边n个没有共同的颜色。
可以先递推求出恰用i种颜色染n个位置的方案数,然后枚举两边的染色数就可以了,代码很简单。
#include<bits/stdc++.h> using namespace std; typedef long long LL; //求C(a,b) ,其中,a,b大小大概不超过1e6级别,很多组数据 const LL mod=1e9+7; const LL M=2e3+5; LL fac[M+5]; //阶乘 LL inv_of_fac[M+5]; //阶乘的逆元 LL qpow(LL x,LL n) //求x^n%mod { LL ret=1; for(; n; n>>=1) { if(n&1) ret=ret*x%mod; x=x*x%mod; } return ret; } void init() { fac[0]=1; for(int i=1; i<=M; i++) fac[i]=fac[i-1]*i%mod; inv_of_fac[M]=qpow(fac[M],mod-2); for(int i=M-1; i>=0; i--) inv_of_fac[i]=inv_of_fac[i+1]*(i+1)%mod; } LL C(LL a,LL b) { if(b<0||a<b) return 0; return fac[a]*inv_of_fac[b]%mod*inv_of_fac[a-b]%mod; } //================================================================ int T,n,m; LL cnt[2005]; //计数假如给定i种颜色,恰把i种颜色全部用上的方案数 void cal_cnt() { cnt[1]=1; for(int i=2;i<=m;i++) { cnt[i]=qpow(i,n); for(int j=1;j<i;j++) cnt[i]=(cnt[i]-cnt[j]*C(i,j)%mod)%mod; cnt[i]=(cnt[i]+mod)%mod; } } int main() { init(); scanf("%d",&T); while(T--) { memset(cnt,0,sizeof(cnt)); scanf("%d%d",&n,&m); cal_cnt(); LL ans=0; for(int i=1;i<=m;i++) for(int j=1;j<=m-i;j++) ans=(ans+C(m,i)*cnt[i]%mod*C(m-i,j)%mod*cnt[j]%mod)%mod; printf("%lld ",(ans+mod)%mod); } }