hdu 6143
题意:2个n长度的字符串,给你m种字符,你可以选择k种组成这2*n的字符串,但前n个用的字符和后n个用的字符不能重叠
思路:组合数,我前n个选i个字符,后n个选j个,即C (m,i)*C(m-i,j)*f(i)*f(j),f(i)代表n长度用i个字符组成的种数
f[i] = i^n- C(i,1)*(x-1)^n+C(i,2)*(x-2)^n-.......
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=2010; 5 const ll MOD=1e9+7; 6 7 ll C[N][N]; 8 ll a[N][N]; 9 10 void init() 11 { 12 C[0][0]=1; 13 for(int i=1; i<N; i++) 14 for(int j=0; j<=i; j++) 15 C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD; 16 for(int i=1;i<N;i++) a[i][1]=i; 17 for(int i=1;i<N;i++){ 18 for(int j=2;j<N;j++) 19 a[i][j]=a[i][j-1]*i%MOD; 20 } 21 } 22 int n,m; 23 24 ll hh(ll x){ 25 ll sum=a[x][n]; 26 for(int i=1;i<=x;i++){ 27 if(i&1) sum=(sum-C[x][i]*a[x-i][n]%MOD+MOD)%MOD; 28 else sum=(sum+C[x][i]*a[x-i][n]%MOD)%MOD; 29 } 30 return sum%MOD; 31 } 32 33 ll c[N]; 34 35 int main(){ 36 int t; 37 scanf("%d",&t); 38 init(); 39 while(t--){ 40 ll ans=0; 41 memset(c,0,sizeof(c)); 42 scanf("%d%d",&n,&m); 43 for(int i=1;i<m;i++){ 44 c[i]=hh(i); 45 } 46 for(int i=1;i<m;i++){ 47 for(int j=1;j<=m-i;j++){ 48 if(i>n||j>n) break; 49 ll x1=C[m][i]*c[i]%MOD; 50 ll x2=C[m-i][j]*c[j]%MOD; 51 ll ss=x1*x2%MOD; 52 ans=(ans+ss)%MOD; 53 } 54 } 55 cout<<(ans+MOD)%MOD<<endl; 56 } 57 }