【康托展开】
展开
1. 例子 求 {2,5,4,3,1} 在集合{1,2,3,4,5}全排列中所处的位置
(1) 比2小得数有 1个 所以为 1*4!个
(2) 比5小得并且在前面没有出现的数(比如 2) 有 3个 所以为 3*3!个
(3) 比4小得并且在前面没有出现的数(比如 2) 有 2个 所以为 2*2!个
(4) 比3小得并且在前面没有出现的数(比如 2) 有 1个 所以为 1*1! 个
所以{2,5,4,3,1} 在集合{1,2,3,4,5}全排列中所处的位置为3*3!+2*2!+1*1!+1*0!=24
void JSContor() { int temp=0,p=1; for(int i=8;i>=0;i--) { int tot=0; for(int j=0;j<i;j++) if(A[j]<A[i]) tot++; temp+=(A[i]-tot-1)*p; p=p*(9-i); } Contor=temp+1; }
如果N很大 可以用线段树做到NlogN
逆展开
例 {1,2,3,4,5}的全排列,并且已经从小到大排序完毕
(1)找出第96个数
首先用96-1得到95
用95去除4! 得到3余23
用23去除3! 得到3余5
用5去除2!得到2余1
用1去除1!得到1余0有3个数比它小的数是4
所以第一位是4
有3个数比它小的数是4但4已经在之前出现过了所以是5(因为4在之前出现过了所以实际比5小的数是3个)
有2个数比它小的数是3
有1个数比它小的数是2
最后一个数只能是1
所以这个数是45321
(2)找出第16个数
首先用16-1得到15
用15去除4!得到0余15
用15去除3!得到2余3
用3去除2!得到1余1
用1去除1!得到1余0
有0个数比它小的数是1
有2个数比它小的数是3 但由于1已经在之前出现过了所以是4(因为1在之前出现过了所以实际比4小的数是2)
有1个数比它小的数是2 但由于1已经在之前出现过了所以是3(因为1在之前出现过了所以实际比3小的数是1)
有1个数比它小得数是2 但由于1,3,4已经在之前出现过了所以是5(因为1,3,4在之前出现过了所以实际比5小的数是1)
最后一个数只能是2
所以这个数是14352