luogu P2525 Uim的情人节礼物 其之壱

LINK:Uim的情人节礼物·其之壱

壱 古代通壹 常在日文中出现。

完全可以使用STL ——>prev_permutation来解决。

不过我简单了解了一下康托展开。

这是一个一个排列对应一个数字的双射.

具体的 对于一个排列 有唯一一个数字和其对应。

计算方法为 见code. 实际上可以使用set或者线段树优化到nlogn.

当然康托展开存在逆过程也比较容易 具体理解可以想象成进制来理解。

const int MAXN=100010;
int n;
int a[MAXN],vis[MAXN];
int fac[MAXN];
inline int cantor()
{
	int cnt=0;
	rep(1,n,i)
	{
		int w=0;
		rep(i+1,n,j)if(a[i]>a[j])++w;
		cnt+=w*fac[n-i];
	}
	return cnt+1;
}
inline void nicantor(int x)
{
	rep(1,n,i)
	{
		int ww=x/fac[n-i]+1;
		x=x-(ww-1)*fac[n-i];
		rep(1,n,j)
		{
			if(vis[j])continue;
			--ww;if(!ww){a[i]=j;vis[j]=1;break;}
		}
	}
	rep(1,n,i)printf("%d ",a[i]);
}
int main()
{
	freopen("1.in","r",stdin);
	get(n);fac[0]=1;
	rep(1,n,i)get(a[i]),fac[i]=fac[i-1]*i;
	int ww=cantor();
	if(ww==1){puts("ERROR");return 0;}
	else nicantor(ww-2);
	return 0;
}
posted @ 2020-04-29 19:29  chdy  阅读(232)  评论(0编辑  收藏  举报