康托展开Cantor expansion 康托逆展开
来源:互联网 发布:监控软件慧眼下载 编辑:程序博客网 时间:2024/06/05 08:41
康托展开
定义
对于n位数的某个排列s[0,n-1],有
X=a[n]∗(n−1)!+a[n−1]∗(n−2)!+...+a[i]∗(i−1)!+...+a[1]∗0!
X 为 s 在整个全排列中的位置-1
a[i] 表示在i位后面出现的小于s[i]的数 的个数
解释
通过上面的定义我们可以知道,康托展开的作用是找出一个排列在全排列中的位置.
公式也特别容易理解:在它后面且比它小的数都可以放在它前面来一个全排列,这样得到的所有排列一定在此排列的前面.
实现
int fact[10]; //fact[i] = i!fact[0] = 1;for(int i = 1; i < 9; ++i) fact[i] = fact[i-1]*i;int kt(int s[], int n) { //n个数的排列s[0,n-1] int ans = 0, cnt = 0; //返回其在全排列中的位置-1 for(int i = 0; i < n; ++i) { cnt = 0; //cnt为在i后面出现的小于s[i]的数的个数 for(int j = i+1; j < n; ++j) if(s[j] < s[i]) ++cnt; ans += cnt*fact[n-i-1]; } return ans;}
康托逆展开
很明显这是一个双射,能正着来肯定也能逆着来.
同样的给出一个位置,我们也应该能还原出这个位置上的排列.
逆着来可以遵循如下流程:
- 当前数 除以 (当前位-1)的阶乘;
- 得到的商i – 此位答案为未出现的数中第i+1大的数(它前面有i个未出现的数),将此数标记表示已出现;
- 得到的余数r – 赋值给当前数, 继续执行1.
上述步骤每重复一次就会确定一位.
下面举个例子:
求从1到5的全排列中第96个全排列(序号为95)
954!商3⏐↓⏐412345−→−−−余23233!商3⏐↓⏐512345−→−−−余552!商2⏐↓⏐312345−→−−−余111!商1⏐↓⏐212345−→−−−余001!商0⏐↓⏐112345
得到答案为{4, 5, 3, 2, 1}
实现
void unKT(int s[], int n, int x) { //找n位全排列[0,n-1]中的第x个排列,存在s里 int j, cnt; bool v[20] = {0}; for(int i = 0; i < n; ++i) { int t = x/fact[n-i-1]; //要找的数后面有t个比它小的数 x %= fact[n-i-1]; for(j = 0; j < n; ++j) if(!v[j]) { if(t == 0) break; --t; } //找未出现的数里第t+1大的数(它前面有t个未出现比它小的数) v[j] = 1; s[i] = j; }}
阅读全文
0 0
- 康托展开Cantor expansion 康托逆展开
- Cantor expansion(康托展开)
- 康托展开及其逆运算【cantor】
- 康托展开 & 康托逆展开
- 康托展开 康托逆展开
- nyoj__139__143__康托展开和康托逆展开
- 康托展开和康托逆展开
- 康托展开和康托逆展开
- 康托展开、康托逆展开;nyoj139,143
- 康托展开与康托逆展开
- 康托展开&康托逆展开 的写法
- 康托展开/逆康托展开
- 康托展开&逆康托展开
- 康托展开
- 康托展开
- 康托展开
- 康托展开
- 康托展开
- 互联网企业安全建设
- E
- jacoco 多个 module 运行 code coverage 测试
- MySQL Q&A : Lock wait timeout exceeded; try restarting transaction
- muduo源码分析之EventLoop
- 康托展开Cantor expansion 康托逆展开
- dfs 实现全排列
- Hibernate注解
- 第一个静态页面的制作模仿
- HQL查询-分页-条件-连接-过滤使用
- Java中Volatile关键字详解
- android EditText长度监听
- CF825D:Suitable Replacement(字符串)
- 第五章 代数方程求解 和其它符号工具