定义: 康拓展开(Cantor expansion)是考察一个排列在全排列中占次位的问题,按照:
X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 展开
其中:a[n] 为占当前未出现的元素中的位次
抽象不懂没有关系,配合下面例子食用:
1.对于{1,2,3}这个组合的任意排列中(代入上面的公式)
名次 康拓值
1 2 3 1 0*2!+ 0*1! + 0*0!
1 3 2 2 0*2!+ 1*1! + 0*0!
2 1 3 3 1*2!+ 0*1!+ 0*0!
2 3 1 4 1*2!+ 1*1!+ 0*0!
3 1 2 5 2*2!+ 0*1!+ 0*0!
3 2 1 6 2*2! + 1*1!+ 0*0!
//这个例子可以知道:康拓值=名次
2.对于{1,2,3,4,5,6,7,8,9}这个组合的任意排列中
求: 8 4 2 6 9 7 1 3 5 的康拓值
第一项 8:当前未出现的:4 2 6 9 7 1 3 5 ;只有红色的9才比8大,所以a[n] = 7,n的值为8(未出现数字的个数);
有:第一项:7*8!
第二项 4:当前未出现的: 2 6 9 7 1 3 5; 6 9 7 5比4大, 所以 a[n] = 3;
有:第二项:3*7!
往下同理。
看到这里,康拓展开相信已经非常明确了,
那么代码实现,最关键的两个步骤:
1. a[n] --- 就是加条件判断的剩下的数的个数;
2.(n-1)! ---就是1.中个数,令n等于个数,阶乘;
以下代码:
//因为对于康拓展开来说,数据可能会很长,开longlong防爆
//这里使用打表法,先把1~10的阶乘输进去
//当然你也可以手动写一个阶乘。
//第一个元素是1, 是因为下标要从0开始,在这里特殊化处理一下防止错误而已
long long factory[]={}1,1,2,6,24,120,720,5040,40320,362880,3628800};
long long Contor(char s[], int n)
{
long long res=0;
for (int i=0; i<n; i++)
{
long long count=0;
for (int j=i+1; j<n; j++)
{
if (s[i]>s[j])
{
++count;
}
}
res += count*factory[n-i-1];
}
return res+1;//res+1就是Contor值
}