ac数论之康托展开

对于n个数的全排列,共有n!中排列方式,如何求某一个序列在整个排列中的次序(从小到大)?

以9的全排列举例:842697513是1-9全排列的第几个?(高中数学排列组合问题,只需要做到不重不漏

首先看第一位为8,那么第一位为1-7的全排列都比它小,共有7*8!个。

在第一位为8的情况下,其次看第二位为4,那么第二位为1-3的全排列都比它小,共有1*3*7!个。

在第一位为8,第二位为4的情况下,那么第三位为1的全排列都比它小,共有1*1*6!个。

在第一位为8,第二位为4,第三位为2的情况下,那么第四位为1-5的全排列都比它小,这里由于第二位4和第三位2已经确定,第四位的可能取值只能为(1,3,5),共有1*1*1*3*5!

在第一位为8,第二位为4,第三位为2,第四位为6的情况下,那么第五位为1-8的全排列都比它小,这里由于第二位为4,第三位为2,第四位为6已经确定,第五位的可能取值只能为(1,3,5,7),共有1*1*1*1*4*4!

......

对于第i位的可能取值,前i位的数字已经确定,且在全排列中每一个数字只能出现一次,只需要比较i位后面的数字比i位数字小的有几个,即可知道第i位的可能取值。


总结上面的方法,计算1-n的全排列


a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!


康托展开

康托展开

康托展开就是一种特殊的哈希函数,它的使用范围是对于n个数的排列进行状态的压缩和存储,例如要对9的全排列进行判重.没有必要

开一个10^9的数组,同时内存也不允许开到那么大的数组.对此,有人提出了优化,即对于一个n的排列数,没有必要开到10^n,因为在一个排列中每个数只出现一次,所以只要前n-1位确定了,前N位就确定了.

但是以上的想法仍不是可行的,因为N可以很大,例如15,所以便引入了康托展开:只需要确定这个排列在总的排列情况中是第几小的就可以了.

例如:我想知道321是{1,2,3}的排列中第几个大的数可以这样考虑第一位是3,当第一位的数小于3时,那排列数小于321 如 123 213 小于3的数有1,2 所以有2*2!个 再看小于第二位2的小于2的数只有一个就是1 所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个所以321是第6个大的数。 2*2!+1*1!是康托展开.


我排第几个

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述

现在有"abcdefghijkl”12个字符,将其所有的排列中按字典序排列,给出任意一种排列,说出这个排列在所有的排列中是第几小的?

输入
第一行有一个整数n(0<n<=10000);
随后有n行,每行是一个排列;
输出
输出一个整数m,占一行,m表示排列是第几位;
样例输入
3
abcdefghijkl
hgebkflacdji
gfkedhjblcia
样例输出
1
302715242
260726926

#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
int power[13];
void db()
{
    power[0]=power[1]=1;
    for(int i=1; i<=12; i++)
        power[i]=power[i-1]*i;
}
int main()
{
    int ncase;
    cin>>ncase;
    db();
    getchar();
    while(ncase--)
    {
        char c[30];
        cin.getline(c,30);
        int l=strlen(c);
        long long sum=0;
        for(int i=0; i<l; i++)
        {
            int tt=0;
            for(int j=l-1; j>i; j--)//从后向前扫描,寻找比自己小的,就是比c[i]位置小的几种情况
                if(c[j]<c[i])
                {
                    tt++;
                }
                //然后在乘以后面所有位数的全排列
                sum+=tt*power[l-i-1];
        }
        cout<<sum+1<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/memeda1141/article/details/79997212