日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

关于数论【康托展开及其逆运算】

發布時間:2025/7/14 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于数论【康托展开及其逆运算】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

表示這個東西背了很多次,但是次次忘,希望這次能夠記住吧。

康托展開:
問45231是n=5的全排列中第幾個排列?
ans:= 3*4! + 3*3! + 1*2! + 1*1! + 0*0! =93
這時求出的是在45231前面全部的排列,排名還要加1
所以對此的做法,就是將階乘前面的求出來,這個就是在a[i]前面,還沒出現過的數字。比如4前面1~3都沒出現而1(或2或3)xxxx肯定在4xxxx前面,因為有四個不定的數字,所以乘上4!

逆運算:
問n=5的全排列中第94個是誰?94先-1
94/4!=3.875
所以第一個數字前面有3個數字
9
4先減3*4!=22
22/3!=3.6666666666666666666666666666667

前面還是有三個,因為4之前用過了,所以是5
由此類推。這個東西常用于狀態壓縮的。

模板題caioj1220:

#include<cstdio> #include<cstring> using namespace std; typedef long long LL; int n,a[20]; LL jc[20]; bool bo[20]; void kangtuo1() {jc[0]=1;for(int i=1;i<=n;i++){scanf("%d",&a[i]);jc[i]=jc[i-1]*i;}LL ans=0;//有多少個這個全排列前面的 memset(bo,false,sizeof(bo));//這個有沒有在前面出現過for(int i=1;i<=n-1;i++){ int k=0;//k表示前面有多少個沒被訪問過的for(int j=1;j<a[i];j++)if(bo[j]==false)k++;bo[a[i]]=true;//當前這個數被訪問過 ans+=k*jc[n-i];//乘以當前個數的階乘 }printf("%lld\n",ans+1); } void kangtuo2() {LL ans;scanf("%lld",&ans);ans--; memset(bo,false,sizeof(bo)); for(int i=1;i<=n;i++){LL k=ans/jc[n-i];//有多少個比第i個位置小的數 ans-=k*jc[n-i];for(int j=1;j<=n;j++)if(bo[j]==false){if(k==0){a[i]=j;bo[a[i]]=true;break;}k--;}}for(int i=1;i<n;i++)printf("%d ",a[i]);printf("%d\n",a[n]); } int main() {scanf("%d",&n);kangtuo1();kangtuo2();return 0; }

?

轉載于:https://www.cnblogs.com/AKCqhzdy/p/7612601.html

總結

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

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