康托展开

关于这个我主要学习了两个内容,关于全跑排列的
一个是任意一个全排列数在所有全排列数中排第几(从小到大或从大到小)
一个是对于由数字1-n组成的全排列数(从小到大或从大到小),任意一位全排列数是多少(求第x个全排列数)

以下例子全都以从小到大为序

求位置

举例

51324

它是数字1-5组成的全排列数
它的位置就是比它晓得全排列数的个数+1

那么比它小的全排列数有多少个呢??

逐位讨论
    对于第一位,它小于5时(有4个数字),无论之后的四位怎么排(共4!种排法)都比它小
        于是 res+=4*4!

    那么第一位取5时
    对于第二位,它小于1时同上
    但是1-5没有数字小于1
        于是 res+=0*3!

    那么前两位取51时
    对于第三位,小于3时同上,但由于1已经用过了,所以只有一个2比它小且没被用过
        于是 res+=1*2!

    前三位取513
    对于第四位,小于2同上
        于是 res+=0*1!

    前四位取5132
    最后一位只有一种方案,因为除四之外所有数全被用过了
        于是 res+=1

res+1即为所求

总结

不难得出,对于1-n的任意全展开数
若第i位数num[i],前i-1位用过的比i小的数为o
res+=(num[i-1]-o)*(n-i)!

说明:
    因为当前i-1位数确定时,只有比num[i]小的数字放在i位上才能够随心所欲地组合
    然而如果对于x<num[i],x出现在了之前i-1位上时,这一位用的数就要-1

所以转换为代码

int WEIZHI(int *num)
{
    int n,res=0;//n为这个数的位数
    for(int i=1;i<=n;i++)
    {
        use=num[i];
        for(int p=1;p<=i;p++)
            if(num[p]<=num[i])use--;//可以将数字为num[i]的情况也减去
        res+=use*JC[num-i];//JC存(num-i)!
    }
    return res;
}

求第x个全排列数

有了上面的基础,此处的算法会好推很多

对于任意1-n组成的第num个全排列数
都有num=a*(n-1)!+b*(n-2)!+……+z*0!+1

举例

51324

51324的位置=4*4!+0*3!+(2-1)*2!+(1-1)*1!+(3-3)*1!+1
注意此处括号内的减数,这就是小于a、b、c...的已经出现的数的个数之和
第一位为有4个小于它且之前没出现过的数->5
第二位为有0个小于它且之前没出现过的数->1
第三位为有1个小于它且之前没出现过的数
    因为1出现过了,所以这个比它小的数为2,这个数为3
.
.
.
51324的位置为97
那么第97个数根据以上过程反推
第一位(97-1)/(4!)=4...3  ==>为5
第二位(97-1-4*4!)=3 (上式余数)
     3/(3!)=0...2       ==>为1(见上述过程)
.
.
.

所以对于1-n的全排列数中的第x个
第i位为

    上次运算的余数c/(n-i)! 的整数商t
    从1-n排列的数中没出现的第t个数
(很难懂,但是我的描述能力仅限于此)

附上代码

int QIUSHU(int x,int n)//1-n全排列数,第x个
{
    int num[n];bool mark[n];//num存结果 mark标记已经出现过的数
    for(int i=1;i<=n;i++)
    {
        pos=x/JC[n-i];//JC存阶乘
        for(i=1;i<=n;i++)
        if(!mark[i])
        {
            if(!pos)break;
            pos--;
        }
        num[i]=1;
        mark[i]=1;
        x=x%JC[n-i];
    }
    for(int i=1;i<=n;i++)printf("%d",num[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值