1. 程式人生 > >康託展開式

康託展開式

應用:

{1,2,3,4,...,n}表示1,2,3,...,n的排列如 {1,2,3} 按從小到大排列一共6個。123 132 213 231 312 321 。 代表的數字 1 2 3 4 5 6 也就是把10進位制數與一個排列對應起來。 他們間的對應關係可由康託展開來找到。 如我想知道321是{1,2,3}中第幾個小的數可以這樣考慮 : 第一位是3,當第一位的數小於3時,那 排列數小於321 如 123、 213 ,小於3的數有1、2 。所以有2*2!個。再看小於第二位2的:小於2的數只有一個就是1 ,所以有1*1!=1 所以小於321的{1,2,3}排列數有2*2!+1*1!=5個。所以321是第6個小的數。 2*2!+1*1!+0*0!就是康託展開。 再舉個例子:1324是{1,2,3,4}排列數中第幾個大的數:第一位是1小於1的數沒有,是0個 0*3! 第二位是3小於3的數有1和2,但1已經在第一位了,所以只有一個數2 1*2! 。第三位是2小於2的數是1,但1在第一位,所以有0個數 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2個,1324是第三個小數。

康託展開式:X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! ,其中a[i]為當前未出現的元素中是排在第幾個(從0開始,即X從0開始)。這就是康託展開。康託展開可用程式碼實現。

long long jiec(long long num){

long long ans = 1;

for(int i = 1; i <= num; i++)

ans *= i;

return ans;

}

for(i = 0; i < count - 1; i++){
    k = 0;
    for(j = i + 1; j < count; j++)
    if(a[i] > a[j])
      k++;
    ans += jiec(count - 1 - i) * k;

  }

(jiec 函式是階乘函式。)