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 }

 

posted on 2017-08-18 11:12  hhhhx  阅读(104)  评论(0编辑  收藏  举报

导航