【模板】康托展开
搜索有时会用到的康托展开与康托收拢
第一行,两个整数n和m,n表示数字1到n构成的全排列,m表示询问数
接下来m行,表示询问,每行两个整数x和y,x=1表示第一种询问,回答y的排名;x=2表示第2种询问,答出排名为y的数字
#include<bits/stdc++.h> #define int long long using namespace std; int cnt,m; int num[15]; int p[15]={1,1,2,6,24,120,720,5040,40320,362880}; int acanter() { int tmp; int nnn=(num[1]-1)*p[cnt-1]; for(int i=2;i<=cnt;i++) { tmp=0; for(int j=1;j<i;j++) { if(num[i]>num[j]) ++tmp; } nnn+=(num[i]-tmp-1)*p[cnt-i]; } return nnn+1; } void nicanter(int k) { bool flag[15]={0}; k--; int i,j,t; for(i=1;i<=cnt;i++) { t=k/p[cnt-i ]; for(j=1;j<=cnt;j++) if(!flag[j]) { if(t==0) break; t--; } num[i]=j; flag[j]=1; k%=p[cnt-i]; } } main() { int x; char y[15]; scanf("%lld%lld",&cnt,&m); for(int i=1;i<=m;i++) { scanf("%lld",&x); if(x==1) { scanf("%s",y+1); for(int i=1;i<=cnt;i++) { num[i]=y[i]-'0'; } printf("%lld\n",acanter()); } else { scanf("%lld",&x); nicanter(x); for(int i=1;i<=cnt;i++) printf("%lld",num[i]); printf("\n"); } } }