024题:
题意:
排列指的是将一组物体进行有顺序的放置。例如,3124是数字1、2、3、4的一个排列。如果把所有排列按照数字大小或字母先后进行排序,我们称之为字典序排列。0、1、2的字典序排列是:
012 021 102 120 201 210
数字0、1、2、3、4、5、6、7、8、9的字典序排列中第一百万位的排列是什么?
思路:
设n = 1e6,这个题可以预处理出1~9位数的组合数分别是sum[1~9];
然后用i遍历从9~1
如果n % sum[i] != 0,那么最高位数字是剩余数字中第n / sum[i] 个数(从0开始)并取出
如果n % sum[i] == 0,那么最高位数字是剩余数字中第n / sum[i] - 1个数(从0开始)并取出,剩余数字由大到小排序,并跳出i循环
这样只需要一次遍历就可以求出第1000000位的排列是多少
代码:
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <algorithm>
#define ll int64_t
#define d int32_t
#define r return
#define mem(a) memset(a, 0, sizeof(a))
using namespace std;
const ll n = 1e6;
ll sum[15];
bool book[15];
//预处理
void init() {
mem(book);
mem(sum);
sum[0] = 1;
for (d i = 1; i <= 9; i++) {
sum[i] = sum[i - 1] * i;
}
}
//求第m个数是多少
void work (ll m) {
for (d i = 9; i >= 1; i--) {
ll t = m / sum[i];
if (m % sum[i] == 0) { //当m%sum[i]==0时
d num = 0;
for (d j = 0; j <= 9; j++) {
if (!book[j]) {
if (num == t - 1) {
printf("%" PRId32, j);
book[j] = 1;
break;
}
num ++;
}
}
for (d j = 9; j >= 0; j--) {
if(!book[j]) {
printf("%" PRId32, j);
}
}
printf("\n");
r;
}
//当m % sum[i] != 0时
d num = 0;
for (d j = 0; j <= 9; j++) {
if (!book[j]) {
if (num == t) {
printf("%" PRId32, j);
book[j] = 1;
break;
}
num ++;
}
}
m %= sum[i];
}
//最后别忘已经固定的个位数
for (d i = 0; i <= 9; i ++) {
if (!book[i]) {
printf("%" PRId32"\n", i);
r;
}
}
r;
}
d main() {
init();
work (n);
r 0;
}
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢