蓝桥杯 排列序数

时间:2021-12-15 11:11:54
标题: 排列序数

X星系的某次考古活动发现了史前智能痕迹。
这是一些用来计数的符号,经过分析它的计数规律如下:
(为了表示方便,我们把这些奇怪的符号用a~q代替)

abcdefghijklmnopq 表示0
abcdefghijklmnoqp 表示1
abcdefghijklmnpoq 表示2
abcdefghijklmnpqo 表示3
abcdefghijklmnqop 表示4
abcdefghijklmnqpo 表示5
abcdefghijklmonpq 表示6
abcdefghijklmonqp 表示7
.....

在一处石头上刻的符号是:
bckfqlajhemgiodnp

请你计算出它表示的数字是多少?
请提交该整数,不要填写任何多余的内容,比如说明或注释。

22952601027516


分析:这道题就是关于全排列的序数问题,自己想出了一个算法

       bckfqlajhemgiodnp是一个序列

      基串是“abcdefghijklmnopq”

      在基串中找到b的索引,是1,所以1*16!

     然后在基串中删掉b, 基串变成“acdefghijklmnopq”

    接着找c的索引,是1,所以  1*15!

    。。。

   最后求出的排列数 大概是  1*16!+1*15!+8*14!+......

  这个算法的原理画一颗树出来,就理解了,就是第一个字母是b的话,那么前面a开头的就有16!种

 

接着上代码:

涉及阶乘,所以用BigInteger才不会超出范围

import java.math.BigInteger;
class Main{
static String baseStr="abcdefghijklmnopq";
static long []j=new long[17];//阶乘数组
static BigInteger b=BigInteger.ZERO;
public static void main(String[] args) {
init();//初始化阶乘数组
System.out.println(f("bckfqlajhemgiodnp"));
}

private static BigInteger f(String str) {
for(int i=0;i<str.length();i++)
{
char a=str.charAt(i);
int index=baseStr.indexOf(a);
b=b.add(new BigInteger(""+index).multiply(new BigInteger(""+j[16-i])));
baseStr=baseStr.replaceAll(a+"", "");
}
return b;
}

private static void init() {
j[0]=1;
for(int i=1;i<=16;i++)
{
j[i]=j[i-1]*i;
}
}

}