You are given a permutation p of numbers 1, 2, ..., n. Let's define f(p) as the following sum:
![](https://i-blog.csdnimg.cn/blog_migrate/3efdae69a84cb36dc59445baf7601270.png)
Find the lexicographically m-th permutation of length n in the set of permutations having the maximum possible value of f(p).
The single line of input contains two integers n and m (1 ≤ m ≤ cntn), where cntn is the number of permutations of length n with maximum possible value of f(p).
The problem consists of two subproblems. The subproblems have different constraints on the input. You will get some score for the correct submission of the subproblem. The description of the subproblems follows.
- In subproblem B1 (3 points), the constraint 1 ≤ n ≤ 8 will hold.
- In subproblem B2 (4 points), the constraint 1 ≤ n ≤ 50 will hold.
Output n number forming the required permutation.
2 2
2 1
3 2
1 3 2
In the first example, both permutations of numbers {1, 2} yield maximum possible f(p) which is equal to 4. Among them, (2, 1) comes second in lexicographical order.
解题思路:本题要求解的是字典序第m大的最优解的方案。首先对于最优方案我们是这样得到的,首先对于1我们应该放置其在位置1或者位置n处,因为如果将1放置在数组的中间则会有更多的(i,j)满足min(i,j)=1,这样肯定比当前方案差,因此1应该放置位置1或者位置n处,存在两种选择。当然对于2应该放置在剩余空位置处的左右两端的其中一个位置,这样依此类推进行放置,最终得到的序列结果肯定是最优的,且这样的序列的个数为2^(n-1)。现在我们要求解字典序第m大的排列方案,首先对于1放置在位置1处对应前2^(n-2)种方案,放置在n处也对应后2^(n-2),这样我们不难想到采用二进制分解的方法来求解第m大的方案。
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 110;
int arr[maxn];
int main() {
int n;
ll m;
int p1, p2;
cin >> n >> m;
p1 = 1;
p2 = n;
m--;
for(int i = n-2, j = 1; i >= 0; --i, ++j) {
if(m&(1LL<<i)) {
arr[p2] = j;
p2--;
} else {
arr[p1] = j;
p1++;
}
}
arr[p1] = n;
for(int i = 1; i <= n; ++i) {
if(i == 1) {
printf("%d", arr[i]);
} else {
printf(" %d", arr[i]);
}
}
printf("\n");
return 0;
}