(7.15)康托展开,就是把全排列转化为唯一对应自然数的算法。它可以建立1 ~ n的全排列与[1, n!]之间的自然数的双向映射。

1、康托展开:

  尽管我并不清楚康托展开的原理何在,这个算法的过程还是比较好记的。正确性之后有机会询问下学长。

  如果从1开始给全排列的排名从大到小编号的话(从0开始也可,建立的是与[0, n!-1]的映射,本质相同),定义rk为排名,a是排列数组,排列有n位(最低位是第0位),那么有公式

  rk - 1 = cnt[n-1] * (n-1)! + cnt[n-2] * (n-2)! + ... + cnt[0] * 0!  

  其中cnt数组的含义是未统计的数字中,小于a[i]的数字有多少个。

  举例:计算排列3 4 2 1对于{1, 2, 3, 4}的排名

  首先取出最高位(第三位),小于数字3的数有两个,所以cnt[3] = 2,rk += 2 * 3!,rk = 12。

  然后取出4,小于4的数有三个,但是3已经被统计过了,所以cnt[2] = 2,rk += 2 * 2!,rk = 16.

  取出2,小于2的只有1,cnt[1] = 1,rk += 1 * 1!,rk = 17。

  最后由于除第0位本身外已经没有数了,cnt[0]恒等于0。所以3 4 2 1的排名为18。

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. int f[10], n;
  6. bool vis[10];
  7. int KtSplay(int *a) {  //康托展开,返回的[1, n!]之间的数
  8. int rk = 0;
  9. cal();
  10. for (int i = 1; i <= n; ++i)
  11. vis[i] = 0;
  12. for (int i = n - 1; i >= 0; --i) {
  13. int u = a[i], cnt = 0;
  14. for (int i = 1; i < u; ++i)
  15. if (!vis[i]) ++cnt;
  16. rk += cnt * f[i];
  17. vis[u] = true;
  18. }
  19. return rk + 1;
  20. }
  21. int a[10];
  22. int main() {
  23. cin >> n;
  24. for (int i = n - 1; i >= 0; --i)
  25. cin >> a[i];
  26. cout << KtSplay(a);
  27. }

(先咕掉逆展开)

(先补一点)

  康托展开的逆过程,就是依照排名来查询排列。

  首先把排名-1(突然发现这样有点麻烦,可能从0开始编排名号更合理,大家看得懂就好)。然后我们考虑康托展开的过程,用带余除法的方式确定每一位数字的排名,进而得到这个数。

  比如我们要计算{1, 2, 3, 4}排列中排第18的排列。

  第三位(最高位):17/3! = 2……5,说明比该位小的数有2个,该位是3。

  第二位:5/2! = 2……1,说明这一位是当前没出现的第2个,该位是4。

  第三位:1/1! = 1……0,说明这一位是2。

  那么最后一位是1。

  所以所求排列是3、4、2、1。

代码:

  1. void KtResplay(int rk) {
  2. --rk;
  3. cal();
  4. for (int i = n - 1; i; --i) {
  5. int k = rk / f[i];
  6. int j = 0;
  7. while (k >= 0) {
  8. ++j;
  9. if (!vis[j])
  10. --k;
  11. }
  12. vis[j] = true;
  13. a[i] = j;
  14. rk = rk % f[i];
  15. }
  16. for (int i = 1; i <= n; ++i)
  17. if (!vis[i]) {
  18. a[0] = i;
  19. break;
  20. }
  21. return;
  22. }

(2019.7.16 坑填了)

【数学】康托展开 && 康托逆展开的更多相关文章

  1. 康托展开&&康托逆展开

    康托展开 简介:对于给定的一个排列,求它是第几个,比如54321是n=5时的第120个.(对于不是1~n的排列可以离散化理解) 做法: ans=a[n]*(n-1)!+a[n-1]*(n-2)!+~~ ...

  2. HDU 1027 Ignatius and the Princess II(康托逆展开)

    Ignatius and the Princess II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ( ...

  3. 康托展开&康托逆展开 的写法

    康托展开 康托展开解决的是当前序列在全排序的名次的问题. 例如有五个数字组成的数列:1,2,3,4,5 那么1,2,3,4,5就是全排列的第0个[注意从0开始计数] 1,2,3,5,4就是第1个 1, ...

  4. nyoj 139——我排第几个|| nyoj 143——第几是谁? 康托展开与逆康托展开

    讲解康托展开与逆康托展开.http://wenku.baidu.com/view/55ebccee4afe04a1b071deaf.html #include<bits/stdc++.h> ...

  5. 康托展开&逆展开算法笔记

    康托展开(有关全排列) 康托展开:已知一个排列,求这个排列在全排列中是第几个 康托展开逆运算:已知在全排列中排第几,求这个排列 定义: X=an(n-1)!+an-1(n-2)!+...+ai(i-1 ...

  6. 康托展开+逆展开(Cantor expension)详解+优化

    康托展开 引入 康托展开(Cantor expansion)用于将排列转换为字典序的索引(逆展开则相反) 百度百科 维基百科 方法 假设我们要求排列 5 2 4 1 3 的字典序索引 逐位处理: 第一 ...

  7. 康托展开与逆康托展开模板(O(n^2)/O(nlogn))

    O(n2)方法: namespace Cantor { ; int fac[N]; void init() { fac[]=; ; i<N; ++i)fac[i]=fac[i-]*i; } in ...

  8. lightoj1060【康托逆展开】

    可以先看些资料:http://blog.csdn.net/keyboarderqq/article/details/53388936 参考谷巨巨:http://blog.csdn.net/azx736 ...

  9. 康托(Cantor)展开

    直接进入正题. 康托展开 Description 现在有"ABCDEFGHIJ”10个字符,将其所有的排列中按字典序排列,给出任意一种排列,说出这个排列在所有的排列中是第几小的? Input ...

随机推荐

  1. robotframework执行自动化不能转换为h5页面的问题解决

    电脑换成win10后,搭建了robotframework环境,执行自动化发现页面不支持h5页面了.请教了大佬,解决办法如下: 1.切换到DOS环境下,执行pip list命令,查看selenium2l ...

  2. Interface 接口详解

    简介 接口主要用来描述类具有哪些功能,并不给出每个功能的具体实现方式.一个类可以实现一个或多个接口,并在需要接口的地方,随时使用实现了响应接口的对象. 在 Java 程序设计语言中,接口不是类,而是对 ...

  3. redis简介以及redis集群配置

    简介: redis 是一个高性能的key-value数据库..它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序 ...

  4. python 作业 批量读取excel文件并合并为一张excel

    1 #!/usr/bin/env python 2 # coding: utf-8 3 4 def concat_file(a,b): 5 #如何批量读取并快速合并文件夹中的excel文件 6 imp ...

  5. IC晶圆缺货涨价浪潮持续上涨 无线路由芯片WiFi模块受波及严重

    正是多事之秋,继受美国贸易战影响后.由于晶圆供不应求,市场各大行业IC纷纷出现了断货,缺货,涨价的现象.这给了本来低迷的经济市场又一重创.WiFi路由芯片的无线路由模块必不可免的受到了波及. 晶圆代工 ...

  6. 秒懂Dubbo接口(原理篇)

    引言 背景 单一应用架构 垂直应用架构 分布式服务架构 流动计算架构 为什么要用 Dubbo? 什么是分布式? 为什么要分布式? Dubbo 的架构 Dubbo 的架构图解 Dubbo 工作原理 Du ...

  7. 快速傅里叶变换(FFT)学习笔记(其一)

    再探快速傅里叶变换(FFT)学习笔记(其一) 目录 再探快速傅里叶变换(FFT)学习笔记(其一) 写在前面 为什么写这篇博客 一些约定 前置知识 多项式卷积 多项式的系数表达式和点值表达式 单位根及其 ...

  8. dup与dup2

    dup与dup2 #include <unistd.h> int dup(int oldfd); /* oldfd: 要复制的文件描述符 返回值: 新的文件描述符 dup调用成功: 有两个 ...

  9. W: Possible missing firmware /lib/firmware/i915/bxt_guc_ver8_7.bin for module i915

    在执行sudo update-initramfs -u过程中 出现这个错误意思就是说少了固件,只要去下载放到/lib/firmware/i915文件夹下就好了. 下载链接如下: https://git ...

  10. python爬虫01在Chrome浏览器抓包

    尽量不要用国产浏览器,很多是有后门的 chrome是首选 百度 按下F12 element标签下对应的HTML代码 点击Network,可以看到很多请求 HTTP请求的方式有好几种,GET,POST, ...