判断全排列的出现次序

来源:互联网 发布:数据表单设计原则 编辑:程序博客网 时间:2024/06/16 13:03

假如你使用模拟全排列计数,基本会超时;

实现原理:康托展开式

X=a[n](n-1)!+a[n-1](n-2)!+…+a[i]*(i-1)!+…+a[2]*1!+a[1]*0![1]

其中a[i]为当前未出现的元素中是排在第几个(从0开始)

列如 {1,2,3} 按从小到大排列一共6个。123 132 213 231 312 321 。

输入321,让你它在全排列中是第几个,321是6;

具体代码:

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>using namespace std;//斐波那契表long int fac[]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};long cantor(int s[],int n){    long int i,j,temp,num;    num=0;    for(i=0;i<n;i++)    {        temp=0;//记录几个数小于这个数        for(int j=i+1;j<n;j++)        {            if(s[j]<s[i])temp++;//判断几个数小于它        }        num += fac[n-i-1]*temp;    }    return num+1;}int main(){    int a[11]={11,10,9,1,2,3,5,8,7,6,4};    cout<<cantor(a,11);    return 0;}

下面还有逆康托公式;

例如 {1,2,3,4,5}的全排列,并且已经从小到大排序完毕,你求出第96个序列是什么?

找出第96个数

首先用96-1得到95

用95去除4! 得到3余23

有3个数比它小的数是4

所以第一位是4

用23去除3! 得到3余5

有3个数比它小的数是4但4已经在之前出现过了所以第二位是5(4在之前出现过,所以实际比5小的数是3个)

用5去除2!得到2余1

有2个数比它小的数是3,第三位是3

用1去除1!得到1余0

有1个数比它小的数是2,第二位是2

最后一个数只能是1

所以这个数是45321

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<windows.h>#include<cmath>using namespace std;int res[12];long int fac[]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};long cantor(int s[],int n){    long int i,j,temp,num;    num=0;    for(i=0;i<n;i++)    {        temp=0;//记录几个数小于这个数        for(int j=i+1;j<n;j++)        {            if(s[j]<s[i])temp++;//判断几个数小于它        }        num += fac[n-i-1]*temp;    }    return num+1;}void uncantor(int x,int k){    memset(res,0,sizeof(res));    int i,j,l,t;    int h[12]={0};    for(i=1;i<=k;i++)    {        t=x/fac[k-i];        x-=t*fac[k-i];        for(j=1,l=0;l<=t;j++)        {            if(!h[j])            {                l++;            }        }        j--;        h[j]=1;        res[i-1]=j;    }}int main(){    int a[11]={11,10,9,1,2,3,5,8,7,6,4};    cout<<cantor(a,11)<<endl;     uncantor(cantor(a,11)-1,11);//利用上面算出来的序号;输出的正好是那个序列     for(int i=0;i<11;i++)    {        cout<<res[i]<<" ";    }    cout<<endl;    return 0;}
0 0
原创粉丝点击