HDU 6143 - Killer Names | 2017 Multi-University Training Contest 8
/*
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\n", ans);
}
}
我自倾杯,君且随意

浙公网安备 33010602011771号