欧拉计划 问题24 字典序排列

本文介绍了一种解决字典序排列问题的方法,通过计算排列组合确定特定位置上的数字,适用于寻找大规模数字排列中的指定项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

欧拉计划24

题目描述

排列指的是将一组物体进行有顺序的放置。例如,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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值