hdu 6143 组合数学+dp

题意: m个字母,组成两个长度为n的字符,其中一个字母不能同时出现在两个串中。问总方案?

 

思路:枚举m个中恰好有i个在第一个串,有j个在第二个串。。然后求个和。。具体其中n个空恰好k种颜色,可以用dp预处理。

dp[j][i]=((dp[j-1][i]*i)%mod+(dp[j-1][i-1]*i)%mod)%mod;

 

代码:

 

#include<bits/stdc++.h>
using namespace std;
#define MEM(a,b) memset(a,b,sizeof(a))
#define bug puts("bug");
#define PB push_back
#define MP make_pair
#define X first
#define Y second
typedef unsigned long long ll;
typedef pair<int,int> pii;
const int maxn=4e5+10;
const int mod=1e9+7;
using namespace std;
int t,m,n,k;
ll C[2005][2005];
ll dp[2005][2005];
ll A(ll x){
    ll ret=1;
    for(int i=1;i<=x;i++)
        ret=(ret*i)%mod;
    return ret;
}
int main(){
    C[1][0] = C[1][1] = 1;
    for (int i = 2; i < 2005; i++){
        C[i][0] = 1;
        for (int j = 1; j < 2005; j++)
            C[i][j] = (C[i - 1][j] + C[i - 1][j - 1])%mod;
    }
    for (ll i = 1; i < 2005; i++){
        dp[i][i]=A(i);
        for (ll j = i+1; j < 2005; j++)
            dp[j][i]=((dp[j-1][i]*i)%mod+(dp[j-1][i-1]*i)%mod)%mod;
    }
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        ll ans=0;
        for(int i=1;i<m;i++)
            for(int j=m-i;j>0;j--){
                ans=(ans+((C[m][i]*dp[n][i])%mod)*((C[m-i][j]*dp[n][j])%mod))%mod;
            }
        printf("%lld\n",ans);
    }
    return 0;
}



posted @ 2017-08-17 19:29  zhangxianlong  阅读(116)  评论(0编辑  收藏  举报