Uim的情人节礼物·其之壱
题目描述
情人节到了,Uim打算给他的后宫们准备情人节礼物。UIm一共有N(1<=N<=9)个后宫妹子(现充去死 挫骨扬灰!)。
为了维护他的后宫的稳定。他通过编程,得出了一个送礼物的最佳顺序。这个我们管不着。
然而他认为,如果什么事情做得太圆满不是什么好事。于是他希望得到 原定顺序 的 前一个字典序的序列。
输入输出格式
输入格式:
第一行一个整数N
第二行N个整数,表示原定排列
输出格式:
前一个排列
输入输出样例
说明
若当前排列已经是第一个,则输出'ERROR'(引号不输出)
分析:
很多大佬都是用$STL$的$prev\_permutation$做的,甚至有大佬搜索、模拟各种奇妙算法过。
这里博主用的是康托展开和逆康托展开。
非常容易,对于给定的排列,求出其康托展开值$m$,然后再求$m-1$的逆康托展开。
Code:
//It is made by HolseLee on 8th Oct 2018 #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,m,f[11],a[11]; char ka[11]; vector<int>v; inline int cantor() { int ret=0,x; for(int i=0; i<n; ++i) { x=0; for(int j=i+1; j<n; ++j) if( (ka[i]-ka[j])>0 ) x++; ret+=x*f[n-i-1]; } return ret; } inline void incantor(int k) { int x; while( !v.empty() ) v.erase(v.end()); for(int i=1; i<=n; ++i) v.push_back(i); for(int i=1; i<n; ++i) { a[i]=v[(x=k/f[n-i])]; v.erase(v.begin()+x); k%=f[n-i]; } a[n]=v[0]; } int main() { ios::sync_with_stdio(false); cin>>n; for(int i=0; i<n; ++i) cin>>ka[i]; f[1]=1; for(int i=2; i<=10; ++i) f[i]=f[i-1]*i; incantor(cantor()-1); for(int i=1; i<=n; ++i) printf("%d ",a[i]); return 0; }