康托展开及康拓逆展开

康拓展开

把一个整数X展开成如下形式:

X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!

其中a[i]为''当前元素''在''所有未出现的元素''中排在第i个(从0开始),并且0<=a[i]<i(1<=i<=n)

为了更好的理解康托展开,举个例子

序列

3 4 6 2 1 7 5 8 0

总共有9个数

第一个数3在未出现的数字排第四 3*(8!)

a[n]即在它之后有多少个比它小,阶乘的阶数从最大的数开始

这样就可以一个一个算出来了

代码实现

int work()
{
	int code=0;
	for(int i=0;i<9;i++)
	{
		int cnt=0;
		for(int j=i+1;j<9;j++)
			if(st[i]<st[j]) cnt++;
		code +=fact[8-i]*cnt;
	}
    return code;
}

康拓逆展开

这个百度百科写的挺好的直接照抄了

例1 {1,2,3,4,5}的全排列,并且已经从小到大排序完毕

(1)找出第96个数

首先用96-1得到95

用95去除4! 得到3余23

有3个数比它小的数是4

所以第一位是4

用23去除3! 得到3余5

有3个数比它小的数是4但4已经在之前出现过了所以第二位是5(4在之前出现过,所以实际比5小的数是3个)

用5去除2!得到2余1

有2个数比它小的数是3,第三位是3

用1去除1!得到1余0

有1个数比它小的数是2,第二位是2

最后一个数只能是1

所以这个数是45321

代码:

void invkt(int k,int *s)
{
    memset(vis2,0,sizeof(vis2));
    for(int i=0;i<9;i++)
    {
        int t=k/fac[8-i];
        int j;
        for( j=0;j<9;j++)
        {
            if(!vis2[j])
            {
                if(t==0)
                    break;
                t--;
            }
        }
        s[i]=j;
        vis2[j]=true;
        k%=fac[8-i];
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值