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;
}