HDU 6143

/*
HDU 6143 - Killer Names [ DP ]  |  2017 Multi-University Training Contest 8
题意:
	m个字母组成两个长为n的序列,两序列中不能包含同一个字母,问对数
分析:
	问题归结于: 包含i(1<=i<=m)个字母的长为n的序列的个数
	则答案为 ans = sum of dp[n][i] * pow(m-i, n);
	易得
		dp[a][b] = b*dp[a-1][b] + C[m-b+1][1] * dp[a-1][b-1]
*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MOD = 1e9+7;
const int N = 2005;
int t, n, m;
LL C[N][N];
void GetComb()//O(n^2)
{
    C[0][0]=1;
    for(int i = 1; i < N; i++){
        C[i][0] = C[i][i] = 1;
        for(int j = 1; j < i; j++)
            C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD;
    }
}
LL PowMod(LL a, LL b)
{
    LL ret = 1;
    while (b)
    {
        if (b&1) ret = ret * a % MOD;
        a = a*a % MOD;
        b >>= 1;
    }
    return ret;
}
LL dp[N][N];
int main()
{
    GetComb();
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d", &n, &m);
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= i; j++)
                dp[i][j] = (j*dp[i-1][j]% MOD + C[m-j+1][1]*dp[i-1][j-1] % MOD) % MOD;
        LL ans = 0;
        for (int i = 1; i <= m; i++)
        {
            ans += dp[n][i] * PowMod(m-i, n) % MOD;
            ans %= MOD;
        }
        printf("%lld
", ans);
    }
}

  

原文地址:https://www.cnblogs.com/nicetomeetu/p/7400620.html