算法分析

题目:link

f(n,k) 表示 n 个数的排列中逆序数为 k 的排列数。

最大的数 n 可能排在第 ni 位,从而产生 i 个与 n 有关的逆序对,去掉 n 之后,剩下的 n1 个数的排列中有 ki 个逆序对。

所以,f(n,k)=i=0n1f(n1,ki)

同理有 f(n,k1)=i=0n1f(n1,k1i)

两式相减,可得 f(n,k)f(n,k1)=f(n1,k)f(n1,kn)

递推公式为

f(n,k)=f(n,k1)+f(n1,k)f(n1,kn)

然后动态规划可得。

C++ 代码

#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::min;
using ll = long long;
const int N = 1010, K = 20010;
const int mod = 1e9 + 7;
int f[N][K];
void init() {
for (int i = 1; i < N; ++i) f[i][0] = 1;
for (int i = 2; i < N; ++i) {
int x = i * (i - 1) / 2;
for (int j = 1; j < min(x + 1, K); ++j) {
f[i][j] = (1ll * f[i][j - 1] + f[i - 1][j]) % mod;
if (j >= i) f[i][j] = (f[i][j] - f[i - 1][j - i] + mod) % mod;
}
}
}
int main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
init();
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
cout << f[n][k] << '\n';
}
return 0;
}