CodeForces-531B1 题解

题目传送门

一道枚举题……

数据范围非常小,考虑暴力枚举全排列。

可以 dfs 两次,第一次求出能使 f(p)f(p) 取得的最大值。第二次求出第 mm 个排列。

注意一下,第二次 dfs 的时候需要按字典序枚举。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <bits/stdc++.h>
#define ll long long
#define INF 1e9
using namespace std;
int n, m, cnt = 1, maxf = -INF;
int res[10];
bool vis[10];
void dfs1(int cur) {
if (cur > n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
int minp = INF;
for (int k = i; k <= j; k++) minp = min(minp, res[k]);
sum += minp;
}
}
maxf = max(maxf, sum);
return ;
}
for (int i = 1; i <= n; i++) {
if (vis[i]) continue;
vis[i] = 1;
res[cur] = i;
dfs1(cur + 1);
vis[i] = 0;
}
}
void dfs2(int cur) {
if (cur > n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
int minp = INF;
for (int k = i; k <= j; k++) minp = min(minp, res[k]);
sum += minp;
}
}
if (sum == maxf) {
if (cnt == m) {
for (int i = 1; i <= n; i++) cout << res[i] << " ";
exit(0);
}
cnt++;
}
return ;
}
for (int i = 1; i <= n; i++) {
if (vis[i]) continue;
vis[i] = 1;
res[cur] = i;
dfs2(cur + 1);
vis[i] = 0;
}
}
signed main() {
ios :: sync_with_stdio(0);
cin >> n >> m;
dfs1(1);
memset(vis, 0, sizeof(vis));
dfs2(1);
return 0;
}