n个元素{1,2,..., n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下:
0 1 2 3 4 5
123 132 213 231 312 321
任务:给定n 以及n 个元素{1,2,..., n }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。
输入
第1 行是元素个数n(n < 15)。接下来的1 行是n个元素{1,2,..., n }的一个排列。
输出
第一行是字典序值,第2行是按字典序排列的下一个排列。
样例输入
8
2 6 4 5 8 1 7 3
样例输出
8227
2 6 4 5 8 3 1
#include <bits/stdc++.h>
using namespace std;
long long n1(long long n){//n!
if(n==1)return 1;
else if(n==0)return 0;
else return n*n1(n-1);
}
long long b[14]={0};
long long n2(long long n){//看剩余的数 正
long long sum=0;
for(long long i=0;i<n-1;i++){
if(b[i]==0)sum++;
}
b[n-1]=1;
return sum;
}
long long n3(long long n,int qw){//看剩余的数 逆
long long sum=0;
for(long long i=0;i<n;i++){
if(b[i]==1){
if(qw==sum){
b[i]=0;
return i+1;
}
sum++;
}
}
return sum;
}
long long n4(long long n,long long sum){//最后一位容错
for(int i=0;i<n;i++){
if(b[i]==1){
sum*=10;
sum+=i+1;
}
}
return sum;
}
long long n5(long long n,long long m){//反着求
long long sum=0;
for(long long i=0;i<n;i++){
sum*=10;
int qw=m/n1(n-i-1);
sum+=n3(n,qw);
m=m%n1(n-i-1);
cout<<"剩余数 "<<m<<" 总 "<<sum<<" 下一 "<<n1(n-i-1)<<" 乘数 "<<qw<<endl;
if(m==0){sum=n4(n,sum);break;}
}
return sum;
}
int main() {
long long n;
cin>>n;
long long a[n];
long long m=0;
for(long long i=0;i<n;i++){
cin>>a[i];
m+=n2(a[i])*n1(n-i-1);//换成数字
}
cout<<m<<endl;
long long m1=m+1;
long long m2=n5(n,m1);
for(int i=n-1;i>=0;i--){
int m3=m2/(pow(10,i));
cout<<m3;
if(i>0)cout<<" ";
m2=m2-m3*pow(10,i);
}
}