【模板】康托展开
搜索有时会用到的康托展开与康托收拢
第一行,两个整数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");
}
}
}

浙公网安备 33010602011771号