康托展开与逆康托展开模板(O(n^2)/O(nlogn))
O(n2)方法:
 namespace Cantor {
     const int N=;
     int fac[N];
     void init() {
         fac[]=;
         for(int i=; i<N; ++i)fac[i]=fac[i-]*i;
     }
     int encode(int* a,int n) {
         int ret=;
         for(int i=n-; i>=; --i) {
             int cnt=;
             for(int j=i+; j<n; ++j)if(a[j]<a[i])++cnt;
             ret+=cnt*fac[n--i];
         }
         return ret;
     }
     vector<int> decode(int x,int n) {
         vector<int> ret;
         vector<int> v;
         for(int i=; i<=n; ++i)v.push_back(i);
         for(int i=n-; i>=; --i) {
             ret.push_back(v[x/fac[i]]);
             v.erase(v.begin()+x/fac[i]);
             x%=fac[i];
         }
         return ret;
     }
 }
O(nlogn)方法(树状数组辅助):
 namespace Cantor {
     const int N=;
     int fac[N],c[N],n,m;
     void init() {
         fac[]=;
         for(int i=; i<N; ++i)fac[i]=fac[i-]*i;
     }
     void setn(int _n) {
         n=_n;
         m=;
         while(m<=n)m<<=;
         for(int i=; i<m; ++i)c[i]=;
     }
     int lowbit(int x) {
         return x&-x;
     }
     void add(int u,int x) {
         while(u<m) {
             c[u]+=x;
             u+=lowbit(u);
         }
     }
     int rnk(int u) {
         int ret=;
         while(u) {
             ret+=c[u];
             u-=lowbit(u);
         }
         return ret;
     }
     int kth(int k) {
         int ret=;
         for(int i=m>>; i; i>>=) {
             if(c[ret+i]<k) {
                 ret+=i;
                 k-=c[ret];
             }
         }
         return ret+;
     }
     int encode(int* a,int _n) {
         setn(_n);
         int ret=;
         for(int i=n-; i>=; --i) {
             ret+=rnk(a[i])*fac[n--i];
             add(a[i],);
         }
         return ret;
     }
     vector<int> decode(int x,int _n) {
         setn(_n);
         vector<int> ret;
         for(int i=; i<=n; ++i)add(i,);
         for(int i=n-; i>=; --i) {
             int t=kth(x/fac[i]+);
             ret.push_back(t);
             add(t,-);
             x%=fac[i];
         }
         return ret;
     }
 }
测试代码:
 int main() {
     Cantor::init();
     int a[]= {,,,};
     do {
         printf("%d\n",Cantor::encode(a,));
     } while(next_permutation(a,a+));
     for(int i=; i<; ++i) {
         vector<int> v=Cantor::decode(i,);
         for(int i=; i<v.size(); ++i)printf("%d%c",v[i]," \n"[i==v.size()-]);
     }
     return ;
 }
输出结果:
康托展开与逆康托展开模板(O(n^2)/O(nlogn))的更多相关文章
- nyoj 139——我排第几个|| nyoj 143——第几是谁? 康托展开与逆康托展开
		
讲解康托展开与逆康托展开.http://wenku.baidu.com/view/55ebccee4afe04a1b071deaf.html #include<bits/stdc++.h> ...
 - 康拓展开 & 逆康拓展开 知识总结(树状数组优化)
		
康拓展开 : 康拓展开,难道他是要飞翔吗?哈哈,当然不是了,康拓具体是哪位大叔,我也不清楚,重要的是 我们需要用到它后面的展开,提到展开,与数学相关的,肯定是一个式子或者一个数进行分解,即 展开. 到 ...
 - HDU1027 Ignatius and the Princess II( 逆康托展开 )
		
链接:传送门 题意:给出一个 n ,求 1 - n 全排列的第 m 个排列情况 思路:经典逆康托展开,需要注意的时要在原来逆康托展开的模板上改动一些地方. 分析:已知 1 <= M <= ...
 - LightOJ1060 nth Permutation(不重复全排列+逆康托展开)
		
一年多前遇到差不多的题目http://acm.fafu.edu.cn/problem.php?id=1427. 一开始我还用搜索..后来那时意外找到一个不重复全排列的计算公式:M!/(N1!*N2!* ...
 - 题解报告:NYOJ 题目143 第几是谁?(逆康托展开)
		
描述 现在有"abcdefghijkl”12个字符,将其按字典序排列,如果给出任意一种排列,我们能说出这个排列在所有的排列中是第几小的.但是现在我们给出它是第几小,需要你求出它所代表的序列. ...
 - 康托展开&逆康托展开学习笔记
		
啊...好久没写了...可能是最后一篇学习笔记了吧 题目大意:给定序列求其在全排列中的排名&&给定排名求排列. 这就是康托展开&&逆康托展开要干的事了.下面依次介绍 一 ...
 - Codeforces-121C(逆康托展开)
		
题目大意: 给你两个数n,k求n的全排列的第k小,有多少满足如下条件的数: 首先定义一个幸运数字:只由4和7构成 对于排列p[i]满足i和p[i]都是幸运数字 思路: 对于n,k<=1e9 一眼 ...
 - CDOJ 485 UESTC 485 	Game (八数码变形,映射,逆cantor展开)
		
题意:八数码,但是转移的方式是转动,一共十二种,有多组询问,初态唯一,终态不唯一. 题解:初态唯一,那么可以预处理出012345678的所有转移情况,然后将初态对012345678做一个映射,再枚举一 ...
 - hdu 1027 Ignatius and the Princess II(正、逆康托)
		
题意: 给N和M. 输出1,2,...,N的第M大全排列. 思路: 将M逆康托,求出a1,a2,...aN. 看代码. 代码: int const MAXM=10000; int fac[15]; i ...
 
随机推荐
- Andorid:日常学习笔记(3)——掌握日志工具的使用
			
Andorid:日常学习笔记(3)——掌握日志工具的使用 使用Android的日志工具Log 方法: Android中的日志工具类为Log,这个类提供了如下方法来供我们打印日志: 使用方法: Log. ...
 - ajax json 异步请求
			
function ajaxTest(){ if (true) { $.ajaxSettings.async = false; var dataJson; $.getJSON("/univer ...
 - C++中引用编译过的C代码为什么要用“extern c”
			
函数经过编译系统的翻译成汇编,函数名对应着汇编标号. 因为C编译函数名与得到的汇编代号基本一样,如:fun()=>_fun, main=>_main 但是C++中函数名与得到的汇编代号 ...
 - 每天一个Linux命令(58)sudo命令
			
sudo命令用来以其他身份来执行命令,预设的身份为root. (1)用法: 用法: sudo [参数] [命令] (2)功能: 功能: sudo可以针对 ...
 - g高分屏DataGrid里面checkbox不显示的解决办法
 - MongoDB环境配置
			
在官网上下载MongoDB可执行文件安装在电脑上后,想要运行需先安装路径下新建一个data文件夹,再在里面新建db文件夹用户存放数据库文件和相关配置. 在bin目录里面运行命令行: 这样MongoDB ...
 - android 加固防止反编译-重新打包
			
http://blog.csdn.net/u010921385/article/details/52505094 1.需要加密的Apk(源Apk) 2.壳程序Apk(负责解密Apk工作) 3.加密工具 ...
 - [转载]OpenWRT使用wifidog实现强制认证的WIFI热点 | 半个橙子
			
首先安装wifidog到OpenWRT的路由器: opkg update opkg install wifidog wifidog依赖下面这些模块: iptables-mod-extra iptabl ...
 - 一览Swift中的常用关键字
			
要学习Swift这门语言,就必须先了解Swift的关键字及对应的解释.这里就列一下在Swift中常用到的关键字. 关键字是类似于标识符的保留字符序列,除非用重音符号(`)将其括起来,否则不能用作标识符 ...
 - WebSocket和HTTP的区别与联系
			
WebSocket是一个计算机通讯协议,在单个TCP连接上提供全双工的通讯模式.WebSocket设计用于Web浏览器和Web服务器之间的通讯,但也可以用于其他的客户端和应用服务器.WebSocket ...