【ACM】nyoj_143_第几是谁_201308071558

第几是谁?
时间限制:3000 ms  |  内存限制:65535 KB
难度:3
描述
现在有"abcdefghijkl”12个字符,将其按字典序排列,如果给出任意一种排列,我们能说出这个排列在所有的排列中是第几小的。但是现在我们给出它是第几小,需要你求出它所代表的序列.
输入
第一行有一个整数n(0<n<=10000);
随后有n行,每行是一个整数m,它代表着序列的第几小;
输出
输出一个序列,占一行,代表着第m小的序列。
样例输入
3
1
302715242
260726926

样例输出
abcdefghijkl
hgebkflacdji
gfkedhjblcia

#include <stdio.h>
#define LEN 12
int JC(int n)
{
    int i,sum=1;
    for(i=1;i<=n;i++)
    sum*=i;
    return sum;
}
int main()
{
    int N;
    scanf("%d",&N);
    while(N--)
    {
        int i,j,k,t,m;
        char str[]="abcdefghijkl";
        char a[15];
        scanf("%d",&m);
        m-=1;
        for(i=0;i<LEN;i++)
        {
            t=m/JC(LEN-i-1);
            for(j=0;j<LEN;j++)
            {
                if(str[j]!='0')//判断str[j]是否用过,与下面 str[j]='0';对应
                {
                    if(t==0)
                    break;   //如果t=0,结束内循环
                    t--;     //此语句作用很大 如果刚开始 T=6 for循环的作用就是:让a[j]不断的向后移动并跳过已经出现过的字母 很强大。
                }
            }
            a[i]=str[j];
            str[j]='0';     //标记,表示这个字母已经使用过
            m%=JC(LEN-i-1);
        }
        a[12]='';   
        printf("%s ",a);       
    }
    return 0;
}

//参考代码如下:
/*
#include"stdio.h"
#include"stdlib.h"
int main()
{
int fac[]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600};//矩阵表
int n=12,k,i,j,t,m;
char s[14];//存放序列
scanf("%d",&m);

while(m--)
{
char a[13]="abcdefghijkl";//字母列表
scanf("%d",&k);
k=k-1;
for(i=0;i<n;i++)//进行12次循环
{
t=k/fac[n-i-1];//求出T是一个数

for(j=0;j<n;j++)
if(a[j]!='0')//与下句的a[j]='0',相呼应,检验是否该字母已经被用过。
{
if(t==0) break;//t为0 就直接跳出最内层的循环
t--; //此语句作用很大 如果刚开始T=6 for循环的作用就是:让a[j]不断的向后移动并跳过已经出现过的字母 很强大。
}
s[i]=a[j];
a[j]='0';//此语句起标记作用,标记字母标中的该字母已经用过。

k%=fac[n-i-1];
}
s[12]='';
printf("%s ",s);
}
system("pause");
return 0;
}
*/

康托展开--逆运算

 {1,2,3,4,5}全排列,并且已经从小到大排序完毕

(1)找出第96个数

首先用96-1得到95

95去除4! 得到323

3个数比它小的数是4

所以第一位是4

23去除3! 得到35

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

5去除2!得到21

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

1去除1!得到10

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

最后一个数只能是1

所以这个数是45321

(2)找出第16个数

首先用16-1得到15

15去除4!得到015

15去除3!得到23

3去除2!得到11

1去除1!得到10

0个数比它小的数是1

2个数比它小的数是但由于1已经在之前出现过了所以是4(因为1在之前出现过了所以实际比4小的数是2

1个数比它小的数是但由于1已经在之前出现过了所以是3(因为1在之前出现过了所以实际比3小的数是1

1个数比它小得数是但由于134已经在之前出现过了所以是5(因为134在之前出现过了所以实际比5小的数是1

最后一个数只能是2

所以这个数是1435

原文地址:https://www.cnblogs.com/xl1027515989/p/3243364.html