与水星人一样,火星人也用数字排列代表要表示的数字,如最多使用5个数字情况下,使用 { 1 , 2 , 3 , 4 , 5 } \{1, 2, 3, 4, 5\} {1,2,3,4,5}表示1, { 1 , 2 , 3 , 5 , 4 } \{1, 2, 3, 5, 4\} {1,2,3,5,4}表示2,……, { 5 , 4 , 3 , 2 , 1 } \{5, 4, 3, 2, 1\} {5,4,3,2,1}表示120。
现给定一个火星人的数字序列,以及一个需要加上的小整数,然后将其转化为火星人的数字表示形式。
N:表示最多使用N位数字,其中 0 < N ≤ 1 0 6 0 < N \leq 10^6 0<N≤106;
M:表示需要加上的值,其中 0 < M < 1 0 6 0 < M < 10^6 0<M<106;
以及N个数字组成的数字序列。
一个数字序列。
由于N的最大取值不超过 1 0 6 10^6 106,显然,不可能直接计算 N ! N! N!。
由于不能采用“水星人”的解题思路,则考虑计算一个数字序列的下一个序列,相当于就是在当前数字序列基础上+1。如果需要在某个数字序列上+M,则循环计算M次下一个序列就能处理。
下标 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
当前序列 | 2 | 4 | 3 | 1 |
交换项 | 1 | 0 | 0 | 0 |
后项排序 | 1 | 3 | 4 | |
第1个大于交换项 | 0 | 1 | ||
交换 | 3 | 1 | 2 | 4 |
所以,序列 { 2 , 4 , 3 , 1 } \{2, 4, 3, 1\} {2,4,3,1}的下一序列为 { 3 , 1 , 2 , 4 } \{3, 1, 2, 4\} {3,1,2,4}。
#include
#include
using namespace std;
int bits[1000005];
// 交换两个整数
void swap(int * a, int * b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
// 输出当前序列
void output(int n) {
for (int i = 1; i <= n; i++) {
printf("%d ", bits[i]);
}
printf("\n");
}
int main() {
int N;
int M;
scanf("%d%d", &N, &M);
// 输入指定序列
for (int i = 1; i <= N; i++) {
scanf("%d", &bits[i]);
}
// 寻找M次下一序列
while (M) {
// 查找需要修改的数字下标
int swap_index = N - 1;
while (bits[swap_index] > bits[swap_index + 1]) {
swap_index--;
}
// 将待修改数字下标后面的所有数字排序
sort(bits + swap_index + 1, bits + N + 1);
// 查找待修数字后面序列中第一个更大的数字,并交换
for (int i = swap_index + 1; i <= N; i++) {
if (bits[i] > bits[swap_index]) {
swap(&bits[swap_index], &bits[i]);
break;
}
}
//output(N);
M--;
}
output(N);
return 0;
}