【模板】康托展开

搜索有时会用到的康托展开与康托收拢 第一行,两个整数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");	
		}
	}
}
 
posted @ 2018-05-06 16:49  Newuser233  阅读(4)  评论(0)    收藏  举报