这道题有多种做法。数学编码、康托展开、STL库等。下面的代码选用的是数学编码。
原理:6个数的全排列共有6!=720种。
如果确定一个1,则其后的5个数有5!=120种。
第一个数可以取1,2,……,6.将它们从小到大编码为0~5.
假定第一个数是1,有120种情况,第二个数可以取2~6,从小到大编码为0~4,每一种编码对应24种情况。以此类推。(类似十进制转N进制)
例如,142356的编码是020000,对应第2*4!+1=49小排列
时间:15毫秒
#include "stdio.h"
int main(){
unsigned char is_used[1002];
int n,m,i,j,Count,c;
int jiecheng[12]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};
while(scanf("%d%d",&n,&m)!=EOF){
for(i=1;i<=n;i++)is_used[i]=0;
if(n>=13){
for(i=1;i<=n-12;i++){
printf("%d ",i);
is_used[i]=1;
}
for(i=1;i<=12;i++){
Count=0;
c=(m-1)/jiecheng[12-i]+1;
m=(m-1)%jiecheng[12-i]+1;
for(j=n-11;j<=n;j++){
if((!is_used[j])&&(Count<c))Count++;
if(Count==c){
printf("%d",j);
is_used[j]=1;
break;
}
}
if(i!=n)printf(" ");
}
}
else{
for(i=1;i<=n;i++){
Count=0;
c=(m-1)/jiecheng[n-i]+1;
m=(m-1)%jiecheng[n-i]+1;
for(j=1;j<=n;j++){
if((!is_used[j])&&(Count<c))Count++;
if(Count==c){
printf("%d",j);
is_used[j]=1;
break;
}
}
if(i!=n)printf(" ");
}
}
printf("\n");
}
return 0;
}
要注意的是,每一组数据的最后一个数后面不能留空格。这不可以通过printf语句用退格键符号(若在某行首,则退格键无效)(苯渣就是因为这个问题WA了6次!!!)