zoukankan      html  css  js  c++  java
  • 康拓展开与逆康拓展开

    一.简介

      首先解释一下,所谓的康拓展开,就是能够通过一个式子,得到一个排列在所有排列中的按字典序排好后的位次。而逆康托展开,则是给出排列的位次,能够计算出排列是什么。

      下面先给出康拓展开的公式   

    其中ai为整数,并且 0≤ai<i ,1≤ i ≤ n。

       ai表示原数的第i位在当前未出现的元素中是排在第几个

      康拓展开是一个双射,因此常用在hash中,比如八数码问题。

      下面我们来演示下康拓展开的具体计算过程

    对于一个1-4的组成的排列{2,3,4,1},那我们应该怎么计算它的康拓展开值rank。

    1. 第一个数是2,后面比它小的就只有1了,rank+=(1*(3)!)
    2. 第二个数是3,后面比它小的也只有1了,rank+=(1*(2)!)
    3. 第三个数是4,后面比它小的也只有1了,rank+=(1*1!)
    4. 最后一个数是1,没有比它小的数了, rank+=(0*0!)

      所以最终rank = 9(排列{1,2,3,4}是0)。通常我们都是从1开始,所以最终rank是10。

      接下来我们再演示下逆康拓展开。

      首先rank--,rank = 9;

      1.9/3!,得1余3,在未选取的数里,2前面正好有一个1个未选取的数,所以第一个数为2。

      2.3/2!,得1余1,在未选取的数里,3前面正好有一个1个未选取的数(2已经被选用了),所以第二个数是3。

      3.1/1!得1余0,在未选取的数里,4前面正好有一个1个未选取的数(2,3已经被选用了),所以第二个数是4。

      4.最后一个数只能是1了。

    二.代码实现

        fac[0] = 1;
        for(int i  = 1;i<N;++i)
        {
            fac[i] =fac[i-1]*i%MOD;
        }
        for(int i =1;i<=N;++i)
        {
            scanf("%d",&a[i]);
            ans = (ans+(sum(a[i]-1)*fac[N-i])%MOD)%MOD;
        }
        cout << ans << endl;

    三.相关习题

  • 相关阅读:
    解决Mac下GDB提示签名错误
    hdu 5015 大数量反复类似操作问题/ 矩阵高速幂
    数据运营报表系统思考 一二
    NGUI 3.5教程(二)Label 标签 (Hello world)、多行文本
    STL 源代码剖析 算法 stl_algo.h -- equal_range
    java字符操作获取汉字的拼音以及其它经常使用工具
    SRAM,SDRAM,网卡
    java.lang.NoClassDefFoundError: ognl/PropertyAccessor解决的方法
    纯手工定制西服怎么鉴别
    缝份_百度百科
  • 原文地址:https://www.cnblogs.com/baihualiaoluan/p/12240719.html
Copyright © 2011-2022 走看看