题意
给定一个(n)个数的排列,求比这个排列大的第(m)个排列。
规定始终有解
数据范围
(1 leq n leq 10000)
(1 leq m leq 100)
思路
- 首先这题可以直接用next_permutation(a, a + n)秒杀。跑(m)次后的排列,即为最终答案
- 考虑next_permutation是怎么实现的。从后向前扫描序列,找到第一个(a[i] > a[i - 1])的位置,因为只有当序列单调下降时,它才不存在更大的排列。
然后将(a[i - 1])与后面比它大的最小数交换。
然后将(a[i - 1])后面的数从小到大排序,这里因为是单调递减的,因此逆序一下就行了。
得到的排列就是比原排列大的最小排列了。
代码
- next_permutation版本
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10010;
int n, m;
int a[N];
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
while(m --) next_permutation(a, a + n);
for(int i = 0; i < n; i ++) printf("%d ", a[i]);
printf("
");
return 0;
}
- 手写版
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10010;
int n, m;
int a[N];
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
while(m --) {
int k = 0;
for(int i = n - 1; i > 0; i --) {
if(a[i] > a[i - 1]) {
k = i - 1;
break;
}
}
int t = n - 1;
for(int i = k + 1; i < n; i ++) {
if(a[i] < a[k]) {
t = i - 1;
break;
}
}
swap(a[k], a[t]);
reverse(a + k + 1, a + n);
}
for(int i = 0; i < n; i ++) printf("%d ", a[i]);
printf("
");
return 0;
}