康托展开及其逆运算

    技术2022-05-20  42

    一、康托展开

    (1)找出45231在这个排列中的顺序

    比4小的数有3个比5小的数有4个但4已经在之前出现过了所以是3个比2小的数有1个比3小的数有两个但2已经在之前出现过了所以是1个比1小的数有0个

    二、康托展开的逆运算

    (1)找出第96个数首先用96-1得到95用95去除4! 得到3余23用23去除3! 得到3余5用5去除2!得到2余1用1去除1!得到1余0

    有3个数比它小的数是4所以第一位是4有3个数比它小的数是4但4已经在之前出现过了所以是5(因为4在之前出现过了所以实际比5小的数是3个)有2个数比它小的数是3有1个数比它小的数是2

    最后一个数只能是1所以这个数是45321

     

    #include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> using namespace std; int main() { int t,i,j,scur; long long sum,st; char str[15]; //freopen("E://input.txt","r",stdin); scanf("%d",&t); while(t--) { sum=0; scanf("%s",&str); for (i=0;i<12;i++) { st=1; scur=str[i]-'a'; for (j=0;j<i;j++) { if (str[j]<str[i]) scur--; } for (j=1;j<=11-i;j++) st*=j; sum+=st*scur; } printf("%ld/n",sum+1); } return 0; }

     

    #include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> using namespace std; int ji[12]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800}; int main() { int t,i,j,pm[13]={1,2,3,4,5,6,7,8,9,10,11,12},scur; int sum,st; char str[15]; // freopen("E://input.txt","r",stdin); scanf("%d",&t); while(t--) { memset(str,0,sizeof(str)); scanf("%ld",&sum); sum--; for (i=1;i<13;i++) { st=ji[12-i]; scur=sum/st; sum-=scur*st; str[i-1]='a'+pm[scur]-1; for (j=scur;j<=12;j++) pm[j]=pm[j+1]; } printf("%s/n",str); for (i=0;i<12;i++) { pm[i]=i+1; } } return 0; }


    最新回复(0)