题目地址:
https://www.luogu.com.cn/problem/P1521
题目描述:
我们说
(
i
,
j
)
(i,j)
(i,j)是
a
1
,
a
2
,
⋯
,
a
N
a_1,a_2,\cdots,a_N
a1,a2,⋯,aN的一个逆序对,当且仅当
i
<
j
i<j
i<j且
a
i
>
a
j
a_i>a_j
ai>aj。例如
[
2
,
4
,
1
,
3
,
5
]
[2,4,1,3,5]
[2,4,1,3,5]的逆序对有
3
3
3个,分别为
(
1
,
3
)
,
(
2
,
3
)
,
(
2
,
4
)
(1,3),(2, 3), (2, 4)
(1,3),(2,3),(2,4)。现在已知
N
N
N和
K
K
K,求
1
,
2
,
3
,
⋯
,
N
1,2,3,\cdots,N
1,2,3,⋯,N的所有特定排列,使得这些排列的逆序对的数量恰好为
K
K
K。输出这些特定排列的数量。例如
N
=
5
N=5
N=5,
K
=
3
K=3
K=3的时候,满足条件的排列有
15
15
15个,它们是:
- [ 1 , 2 , 5 , 4 , 3 ] [1, 2, 5, 4, 3] [1,2,5,4,3];
- [ 1 , 3 , 4 , 5 , 2 ] [1, 3, 4, 5, 2] [1,3,4,5,2];
- [ 1 , 3 , 5 , 2 , 4 ] [1, 3, 5, 2, 4] [1,3,5,2,4];
- [ 1 , 4 , 2 , 5 , 3 ] [1, 4, 2, 5, 3] [1,4,2,5,3];
- [ 1 , 4 , 3 , 2 , 5 ] [1, 4, 3, 2, 5] [1,4,3,2,5];
- [ 1 , 5 , 2 , 3 , 4 ] [1, 5, 2, 3, 4] [1,5,2,3,4];
- [ 2 , 1 , 4 , 5 , 3 ] [2, 1, 4, 5, 3] [2,1,4,5,3];
- [ 2 , 1 , 5 , 3 , 4 ] [2, 1, 5, 3, 4] [2,1,5,3,4];
- [ 2 , 3 , 1 , 5 , 4 ] [2, 3, 1, 5, 4] [2,3,1,5,4];
- [ 2 , 3 , 4 , 1 , 5 ] [2, 3, 4, 1, 5] [2,3,4,1,5];
- [ 2 , 4 , 1 , 3 , 5 ] [2, 4, 1, 3, 5] [2,4,1,3,5];
- [ 3 , 1 , 2 , 5 , 4 ] [3, 1, 2, 5, 4] [3,1,2,5,4];
- [ 3 , 1 , 4 , 2 , 5 ] [3, 1, 4, 2, 5] [3,1,4,2,5];
- [ 3 , 2 , 1 , 4 , 5 ] [3, 2, 1, 4, 5] [3,2,1,4,5];
- [ 4 , 1 , 2 , 3 , 5 ] [4, 1, 2, 3, 5] [4,1,2,3,5]。
输入格式:
输入共第一行,两个整数
N
N
N和
K
K
K。
输出格式:
将
1
⋯
N
1\cdots N
1⋯N的逆序对数量为
K
K
K的特定排列的数量输出。为了避免高精度计算,请将结果对
10000
10000
10000取模后再输出。
数据范围:
对于全部数据,保证
N
≤
100
N \le 100
N≤100,
K
≤
N
×
(
N
−
1
)
/
2
K \le N\times (N-1)/2
K≤N×(N−1)/2。
设 f [ n ] [ k ] f[n][k] f[n][k]是 1 ∼ n 1\sim n 1∼n逆序对恰好有 k k k个的排列数量,其可以按照 n n n这个数字在什么位置来分类。如果 n n n在倒数第 i i i个位置,那么 n n n后面 i − 1 i-1 i−1个数, n n n和它们形成了 i − 1 i-1 i−1个逆序对,所以不含 n n n的逆序对个数应该是 k − i + 1 k-i+1 k−i+1个。所以: f [ n ] [ k ] = ∑ i = 1 n f [ n − 1 ] [ k − i + 1 ] = ∑ i = 0 n − 1 f [ n − 1 ] [ k − i ] f[n][k]=\sum_{i=1}^{n} f[n-1][k-i+1]=\sum_{i=0}^{n-1} f[n-1][k-i] f[n][k]=i=1∑nf[n−1][k−i+1]=i=0∑n−1f[n−1][k−i]其中 f [ 0 ] [ 0 ] = 1 f[0][0]=1 f[0][0]=1。代码如下:
#include <iostream>
using namespace std;
const int N = 5010, MOD = 10000;
int f[N][N];
int n, k;
int main() {
scanf("%d%d", &n, &k);
f[0][0] = 1;
for (int i = 1; i <= n; i++)
for (int j = 0; j <= k; j++)
for (int l = 0; l <= min(j, i - 1); l++)
f[i][j] = (f[i][j] + f[i - 1][j - l]) % MOD;
printf("%d\n", f[n][k]);
}
时间复杂度 O ( n 2 k ) O(n^2k) O(n2k),空间 O ( n k ) O(nk) O(nk)。