比大小
比大小
题目描述 现在有"abcdefghijkl”12个字符,将其所有的排列中按字典序排列,给出任意一种排列,说出这个排列在所有的排列中是第几小的?
| 输入第一行有一个整数n(0<n<=10000);随后有n行,每行是一个排列; | 样例输入3abcdefghijklhgebkflacdjigfkedhjblcia |
|---|---|
| 输出输出一个整数m,占一行,m表示排列是第几位; | 样例输出1302715242260726926 |
| 时间限制C/C++语言:2000MS其它语言:4000MS | 内存限制C/C++语言:65536KB其它语言:589824KB |
本题使用康托展开:

这个展开怎么理解呢?我们每一位计算的都是前面和本数字一样、本位比本数字小的数字个数。就拿1324做例子,第一位1因为没有比1小的,所以是0;而第二位3,我们实际计算的是第一位也是1、但是第二位比3小的数字个数,因为1已经用过了,所以这一位只能是2,所以是1*2!这个2是因为接下来还有两位,根据全排列计算出来的情况总数。正是因为这样的计算方法,每次计算的情况才没有重复,才能加和。
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[]used=new int[12];
long[]mut=new long[12];
//先把阶乘计算出来
for(int i=1;i<12;i++){
long ans=1;
for(int j=1;j<=i;j++){
ans*=j;
}
mut[i]=ans;
}
for(int i=0;i<n;i++){
Arrays.fill(used,0);
long ans=0;
String string=sc.next();
//从头到尾,一个字符一个字符地分析
for(int j=0;j<12;j++){
int c=string.charAt(j)-'a';
used[c]=1;
int count=0;
for(int k=0;k<c;k++){
//count是计算有几个比当前字符小的字符还没有使用
if(used[k]==0){
count++;
}
}
//阶乘只和位置有关
ans+=count*mut[11-j];
}
//输出从1开始,所以要加1
System.out.println(ans+1);
}
}
}

浙公网安备 33010602011771号