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); } }
我自倾杯,君且随意