题目大意:
(1)给定一个排列,问排列的序号.
(2)给定一个序号,要求构造出给定序号的排列.
题解:
首先要知道怎么得出排列的序号.
假如序列的长度为$n$,且第$i$个元素为$P_i$.
则序号为:$\sum_{i=1}^{n}(n-i)!\sum_{j=i+1}^{n}[P_i>P_j]$
这样的话可以$O(n^2)$算出排列的序号.
构造序列的话也是一个道理,我是暴力的,没管复杂度...
代码:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
typedef unsigned long long llu;
int a[21],ans[21];
llu fac[21];
bool ok[21];
int main(){
int n,Q,i,j;
char s[10];
cin>>n>>Q;
llu x;
for(fac[0]=i=1;i<=20;++i)
fac[i]=fac[i-1]*i;
int temp;
while(Q--){
scanf("%s",s);
if(s[0]=='P'){
cin>>x;
--x;
for(i=1;i<=n;++i)
a[i]=x/fac[n-i],x-=a[i]*fac[n-i];
memset(ok,1,sizeof ok);
for(i=1;i<=n;++i){
temp=0;
for(j=1;j<=n;++j){
if((temp+=ok[j])==a[i]+1)
break;
}
ok[ans[i]=j]=0;
}
for(i=1;i<=n;++i){
if(i!=1)
putchar(' ');
printf("%d",ans[i]);
}
puts("");
}
else{
for(i=1;i<=n;++i)
scanf("%d",&a[i]);
for(x=0,i=1;i<=n;++i){
for(temp=0,j=i+1;j<=n;++j)
temp+=(a[i]>a[j]);
x+=fac[n-i]*temp;
}
cout<<x+1<<endl;
}
}
return 0;
}