【洛谷P3014】Cow Line

题目大意:康托展开和逆康托展开模板题。

题解:
注:20!约为 2e18。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=21;
typedef long long LL;

char s[4];
LL n,q,a[maxn],fac[maxn];
bool vis[maxn];

void prework(){
	fac[0]=1;
	for(int i=1;i<=20;i++)fac[i]=fac[i-1]*i;
}
LL cantor(){
	LL ret=0;
	for(int i=1;i<=n;i++){
		int cnt=0;
		for(int j=1;j<=i;j++)if(a[j]<=a[i])++cnt;
		ret+=(a[i]-cnt)*fac[n-i];
	}
	return ret+1;
}
void icantor(LL ret){
	--ret;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++){
		LL cnt=ret/fac[n-i];
		ret%=fac[n-i];
		for(int j=1;j<=n;j++){
			if(!vis[j]){
				if(!cnt){
					a[i]=j,vis[j]=1;break;
				}
				--cnt;
			}
		}
	}
}

int main(){
	prework();
	printf("%lld
",fac[20]);
	scanf("%lld%lld",&n,&q);
	while(q--){
		scanf("%s",s+1);
		if(s[1]=='Q'){
			for(int i=1;i<=n;i++)scanf("%d",&a[i]);
			printf("%lld
",cantor());
		}else{
			LL ret;scanf("%lld",&ret);
			icantor(ret);
			for(int i=1;i<=n;i++)printf("%d%c",a[i],i==n?'
':' ');
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10775812.html