博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
康托展开 + 逆展开
阅读量:5141 次
发布时间:2019-06-13

本文共 2542 字,大约阅读时间需要 8 分钟。

{\displaystyle X=a_{n}(n-1)!+a_{n-1}(n-2)!+\cdots +a_{1}\cdot 0!}

康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的(Wiki)

用他可以监视一个排列的状态,减少了 vis 数组的空间开销。

1 /** 2  *  Fuck you. 3  *  I love you too. 4  */ 5  6 #include
7 #define lson i<<2 8 #define rson i<<2|1 9 #define LS l,mid,lson10 #define RS mid+1,r,rson11 #define mem(a,x) memset(a,x,sizeof(a))12 #define gcd(a,b) __gcd(a,b)13 #define ll long long14 #define ull unsigned long long15 #define lowbit(x) (x&-x)16 #define enld endl17 #define mian main18 #define itn int19 #define prinft printf20 21 const double PI = acos (-1.0);22 const int INF = 0x3f3f3f3f;23 const int EXP = 1e-8;24 const int N = 1e5 + 5;25 const int MOD = 1e9 + 7;26 const int MAXN = 1e5 + 5;27 28 using namespace std;29 30 int fac[] = {
1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //预处理计算康托31 int n;32 string s;33 34 int contor() {35 int sum = 0;36 for (int i = 0; i < n; i++) {37 int cnt = 0;38 for (int j = i + 1; j < n; j++) {39 if (s[i] > s[j]) //计算ai的值40 cnt++;41 }42 sum += cnt * fac[n - i - 1];43 }44 return sum + 1;45 }46 47 int main() {48 while (cin >> n) {49 cin >> s;50 cout << contor() << endl;51 }52 return 0;53 }
View Code

 

双射也就是说,康托可以逆向进行,由X推出原来的那个数。

求 n 位数全排列的第 x 大的排列。

1 /** 2  *  Fuck you. 3  *  I love you too. 4  */ 5  6 #include
7 #define lson i<<2 8 #define rson i<<2|1 9 #define LS l,mid,lson10 #define RS mid+1,r,rson11 #define mem(a,x) memset(a,x,sizeof(a))12 #define gcd(a,b) __gcd(a,b)13 #define ll long long14 #define ull unsigned long long15 #define lowbit(x) (x&-x)16 #define enld endl17 #define mian main18 #define itn int19 #define prinft printf20 21 const double PI = acos (-1.0);22 const int INF = 0x3f3f3f3f;23 const int EXP = 1e-8;24 const int N = 1e5 + 5;25 const int MOD = 1e9 + 7;26 const int MAXN = 1e5 + 5;27 28 using namespace std;29 30 int fac[] = {
1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //预处理计算康托31 int n, x;32 int vis[10] = {
0};33 string s;34 35 void reverse_contor () {36 int j;37 x--;38 for (int i = 0; i < n; i++) {39 itn r = x / fac[n - i - 1];40 x %= fac[n - i - 1];41 for (j = 1; j <= n; j++)42 if (vis[j] == 0 && r-- == 0)43 break;44 vis[j] = 1;45 s[i] = j + '0';46 }47 }48 49 int main() {50 while (cin >> n >> x) {51 mem(vis,0);52 reverse_contor();53 for(int i=0;i
View Code

转载于:https://www.cnblogs.com/chunibyo/p/9396751.html

你可能感兴趣的文章
Sql Server 中由数字转换为指定长度的字符串
查看>>
tmux的简单快捷键
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
php match_model的简单使用
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
移动开发平台-应用之星app制作教程
查看>>
如何在maven工程中加载oracle驱动
查看>>
一句话说清分布式锁,进程锁,线程锁
查看>>
服务器解析请求的基本原理
查看>>
[HDU3683 Gomoku]
查看>>
下一代操作系统与软件
查看>>
Python IO模型
查看>>
DataGridView的行的字体颜色变化
查看>>
[Serializable]的应用--注册码的生成,加密和验证
查看>>
Android-多线程AsyncTask
查看>>
LeetCode【709. 转换成小写字母】
查看>>
如果没有按照正常的先装iis后装.net的顺序,可以使用此命令重新注册一下:
查看>>
【题解】青蛙的约会
查看>>
autopep8
查看>>
Android 官方新手指导教程
查看>>