hdu 6143 Killer Names(动规)

题意:这个题其实就是给你n个块,有m种颜色,问你有多少种涂色方案,但是题目上是有两个n块,还是m个颜色

思路:这个题还是没想到,问题的关键在于不知道怎么去处理在组合数的时候怎么去掉重复的部分,只局限于数学方面的思考,完全没有想到用动规可以一直维护这个东西,去过能跳出组合数的圈估计还有机会想到这个维护。(下次争取本题用第二类斯特林数的做法,立个fag)

代码:(为什么我以前的组合数板子能一直T,玄不救非)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=2007;
#define MOD 1000000007
long long C[maxn][maxn];
long long dp[maxn];
void get_C()
{
    for(int i=1;i<=2005;i++)
    {
        C[0][i]=C[i][i]=1;
        for(int j=1;j<i;j++)
        {
            C[j][i]=(C[j-1][i-1]+C[j][i-1])%MOD;    //用动态规划求出组合数的转移方程
        }
    }
}
LL qmod(LL a ,LL b)       //快速幂
{
    LL res=1;
    while(b)
    {
        if(b & 1)
             res =res*a%MOD;
        a =a*a%MOD;
        b>>=1;
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    get_C();
    while(T--){
        int n,m;
        scanf("%d%d",&n,&m);
        dp[1]=1;
        for(int i=2;i<=n;i++){
            LL ans=0;
            for(int j=1;j<i;j++){
                ans+=C[j][i]*dp[j];
                if(ans>MOD)ans%=MOD;
            }
            dp[i]=(qmod(i,n)-ans+MOD)%MOD;
        }
        LL ans=0;
        int cnt=0;
        int k=m<=n?m-1:n;
        for(int i=1;i<=k;i++){
            cnt=(((C[i][m]*dp[i])%MOD)*qmod(m-i,n))%MOD;
            ans+=cnt;
            ans%=MOD;
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2018-07-14 14:29  啦啦啦天啦噜  阅读(149)  评论(0编辑  收藏  举报