康拓展开
Posted yijiull
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了康拓展开相关的知识,希望对你有一定的参考价值。
1 #include <bits/stdc++.h> 2 using namespace std; 3 //康托展开求法: 4 //比如2143 这个数,求其展开: 5 //从头判断,至尾结束, 6 //① 比 2(第一位数)小的数有多少个->1个就是1,1*3! 7 //② 比 1(第二位数)小的数有多少个->0个0*2! 8 //③ 比 4(第三位数)小的数有多少个->3个就是1,2,3,但是1,2之前已经出现,所以是 1*1! 9 //将所有乘积相加=7 10 //比该数小的数有7个,所以该数排第8的位置。 11 int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //i的阶乘为fac[i] 12 // 康托展开-> 表示数字a是 a的全排列中从小到大排,排第几 13 // n表示1~n个数 a数组表示数字。 14 int kangtuo(int n, char a[]){ 15 int sum = 0; 16 for(int i = 0; i < n; i++){ 17 int t = 0; 18 for(int j = i + 1; j < n; j++) 19 if(a[i] > a[j]) t++; 20 sum += t * fac[n - i - 1]; 21 } 22 return sum+1; 23 } 24 //逆运算的方法: 25 //假设求4位数中第17个位置的数字。 26 //① 17减去1 → 16 27 //② 16 对3!作除法 → 得2余4 28 //③ 4对2!作除法 → 得2余0 29 //④ 0对1!作除法 → 得0余0 30 //据上面的可知: 31 //我们第一位数(最左面的数),比第一位数小的数有2个,显然 第一位数为→ 3 32 //比第二位数小的数字有2个,所以 第二位数为→4 33 //比第三位数小的数字有0个,所以第三位数为→1 34 //第四位数剩下 2 35 //该数字为 3412 (正解) 36 //int fac[] = {1,1,2,6,24,120,720,5040,40320}; 37 //康托展开的逆运算,{1...n}的全排列,中的第k个数为s[] 38 void reverse_kangtuo(int n, int k, char s[]){ 39 int vis[8]={0}; 40 s[k] = 0; 41 --k; 42 for(int i = 0; i < n; i++){ 43 int t = k / fac[n - i - 1]; 44 int j; 45 for (j = 1; j <= n; j++){ 46 if (!vis[j]){ 47 if (t == 0) break; 48 --t; 49 } 50 } 51 s[i] = ‘0‘ + j; 52 vis[j] = 1; 53 k %= fac[n - i - 1]; 54 } 55 } 56 int main(){ 57 int n; 58 char s[11]; 59 while(cin>>n) { 60 reverse_kangtuo(4, n , s); 61 cout<<s<<endl; 62 } 63 }
以上是关于康拓展开的主要内容,如果未能解决你的问题,请参考以下文章