康拓展开

有关康拓展开的介绍,请看百度百科:http://baike.baidu.com/view/437641.htm

下面是康拓展开的逆运算的函数,acm中常常用到:

#include<iostream>

using namespace std;

int  fac[] = {1,1,2,6,24,120,720,5040,40320}; //i的阶乘为fac[i]  
/*{1...n}的全排列,中的第k个数为s[]  */  
void invKT(int n, int k, int s[])  
{  
    int i, j, t, vst[8]={0};  
    k--;  
    for (i=0; i<n; i++) //0 到 n-1 分别对应了要求的数组s[]的下标序号 
    {  
        t = k/fac[n-i-1];  //从 (n-1)!开始   t为比第[i]小的个数
        for (j=1; j<=n; j++)    //判断数字从1 到 n 哪些数字没有用
            if (!vst[j])  //如果这个数字没有使用,并且比她小的数有0个,那么这个数i就是要找的数
            {  
                if (t == 0) break;  
                t--;  //找到比她小的有0个的数
            }  
            s[i] = j;        
            vst[j] = 1;  
            k %= fac[n-i-1];  
    }  
}  

int main()
{
    int s[4];
    invKT(4,3,s);//找1,2,3,4的第3个
    for(int i=0;i < 4; ++i)
        cout<<s[i] <<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/wang7/p/2482160.html