题目链接
题目描述
排列指的是将一组物体进行有顺序的放置。例如,3412是数字1、2、3、4的一个排列。如果把所有排列按照数字大小或字母先后进行排序,我们称之为字典序排列。0、1、2的字典序排列是:012 021 102 120 201 210 。
数字0、1、2、3、4、5、6、7、8、9的字典序排列中第一百万位的排列是。
思路
当排第i位时,后面还10-i位可以排,有全排列(10-i)!种情况,再乘比这个数小的个数 就是之前排过的个数
举个栗子:
1 2 3 4的情况
3412:
排第一位3时,后面还有(4-1)个空,共3!=6种情况,比3小的数有1 2 其中未使用的数有1 2两个,那么在排第一位前有2×3!=12个数
排第二位4时,后面还有(4-2)个空,共2!=2种情况,比4小的数有1 2 3 其中未使用的有1 2两个,那么在排第二位前有2×3!+2×2!=16个数
排第三位1时,后面还有(4-3)个空,共1!=1种情况,比1小且未使用的数有0个,那么在排第三位前有2×3!+2×2!+0×1!=16个数
排第四位2时,后面还有(4-4)个空,共0!=1种情况,比2小的数有1,其中未使用的数有0个,那么在排第四位前有2×3!+2×2!+0×1!+0×0!=16个数
所以3412是第17个数。
推广一下,第n个数前面有n-1个数,那么每位abcdefghij满足的条件就是a×(10-1)!+b×(10-2)!+……+j(10-10)!=n-1,以此为思路,只需要从大到小来遍历每个数即可,由于唯一性且存在阶乘的关系,不可能存在重复的数,因此不需要额外条件
AC代码
from decimal import *
from math import *
from numpy import *
a,i,b,s=[0,0,0,0,0,0,0,0,0,0],9,[],0 # a数组用来标记0-9这10个数字,避免重复,1代表使用
# i是位数,0-9一共可以排10个位,每排一个位i就减1
# b数组用来存储这个数的每一位
# s代表在这个数之前有多少个数,第1e6个数,前面就有1e6-1个数
while(i>=0): # 排第一位时,后面有9位剩余
j=9 # 从9到0进行遍历
while(j>=0):
geshu=0
for k in range(j): # 计算在j前有多少个未使用且比j小的数的个数
if a[k]==0:geshu+=1
if s+geshu*factorial(i)>1e6-1: # 不满足条件就减1继续循环,否则跳出该循环
j-=1
else:break
while(j>=0): # 这时候还不一定确定这位,有可能是用过了,用a数组检验一下是否用过
if a[j]==0 :break
else :j-=1
geshu=0 # 此时比j小的个数需要重新计算
for k in range(j):
if a[k]==0:geshu+=1
s+=geshu*factorial(i) # 在排完第10-i位后此时之前有几个数
a[j]=1 # 将这个数标记为用过
b.append(j) # 在b数组后添加该数
i-=1 # 排下一位
if s==1e6-1:print(b) # 验证一下s是不是真的是1e6-1