日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[总结] 康托展开及其逆运算

發布時間:2024/4/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [总结] 康托展开及其逆运算 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這里先貼一道例題

我們先科普一下康托展開

定義:

X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

ai為整數,并且0<=ai<i(1<=i<=n)

簡單點說就是,判斷這個數在其各個數字全排列中從小到大排第幾位。

比如 1 3 2,在1、2、3的全排列中排第2位。

康托展開有啥用呢?

維基:n位(0~n-1)全排列后,其康托展開唯一且最大約為n!,因此可以由更小的空間來儲存這些排列。由公式可將X逆推出對應的全排列。

它可以應用于哈希表中空間壓縮,

而且在搜索某些類型題時,將VIS數組量壓縮。比如:八數碼,魔板等題

康托展開求法:

比如 2 1 4 3 這個數,求其展開:

從頭判斷,至尾結束,

① 比 2(第一位數)小的數有多少個->1個 就是1,1*3!

② 比 1(第二位數)小的數有多少個->0個 0*2!

③ 比 4(第三位數)小的數有多少個->3個 就是1,2,3,但是1,2之前已經出現,所以是 1*1!

將所有乘積相加=7

比該數小的數有7個,所以該數排第8的位置。

1234 ?1243 ?1324 ?1342 ?1423 ?1432
2134 ?2143 ?2314 ?2341 ?2413 ?2431
3124 ?3142 ?3214 ?3241 ?3412 ?3421
4123 ?4132 ?4213 ?4231 ?4312 ?4321

放一下程序的實現

int contor(int x[]){int p=0;for(int i=1;i<=n;i++){int t=0;for(int j=i+1;j<=n;j++){if(x[i]>x[j]) t++;}p+=t*fac[n-i];}return p+1; }

康托展開的逆:

康托展開是一個全排列到自然數的雙射,可以作為哈希函數。

所以當然也可以求逆運算了。

逆運算的方法:

假設求4位數中第19個位置的數字。

① 19減去1 ?→ 18

② 18 對 3! 作除法 → 得3余0

③ ?0對 2! 作除法 → 得0余0

④ ?0對 1! 作除法 → 得0余0

據上面的可知:

我們第一位數(最左面的數),比第一位數小的數有3個,顯然 第一位數為→ 4

比第二位數小的數字有0個,所以 第二位數為→1

比第三位數小的數字有0個,因為1已經用過,所以第三位數為→2

第四位數剩下 3

該數字為 ?4123 ?(正解)

?

再上代碼

void reverse_contor(int x){memset(vis,0,sizeof vis);x--;int j;for(int i=1;i<=n;i++){int t=x/fac[n-i];for(j=1;j<=n;j++){if(!vis[j]){if(!t) break;t--;}}printf("%d ",j);vis[j]=1;x%=fac[n-i];}puts(""); }

?

轉自

轉載于:https://www.cnblogs.com/YoungNeal/p/8504123.html

總結

以上是生活随笔為你收集整理的[总结] 康托展开及其逆运算的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。