题意:给你k个数Si,然后给你一个等式 H= ∑ Si ∗ (K − i)! (i=(1->k)且0 ≤ Si ≤ K − i). 叫你求出第H个全排列
其实这是一个康托展开:X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! ,其中a[i]为当前未出现的元素中是排在第几个(从0开始)。这就是康托展开。我们也可以找规律解决
接着就是二分树状数组解决第S+1个未出现的位置的经典题了
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #include<string> #include<cstdio> #include<cstring> #include<stdlib.h> #include<iostream> #include<algorithm> using namespace std; #define eps 1E-8 /*注意可能会有输出-0.000*/ #define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型 #define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化 #define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0 #define mul(a,b) (a<<b) #define dir(a,b) (a>>b) typedef long long ll; typedef unsigned long long ull; const int Inf=1<<28; const double Pi=acos(-1.0); const int Mod=1e9+7; const int Max=50010; int bit[Max],num[Max],n; int lowbit(int x) { return x&(-x); } void Add(int x,int y) { while(x<=n) { bit[x]+=y; x+=lowbit(x); } return; } int Sum(int x) { int sum=0; while(x) { sum+=bit[x]; x-=lowbit(x); } return sum; } int Dic(int sma,int big,int num) { while(sma<big) { int mid=(sma+big>>1); if(Sum(mid)>=num) big=mid; else sma=mid+1; } Add(big,-1); return big; } int main() { int t,num; scanf("%d",&t); while(t--) { scanf("%d",&n); memset(bit,0,sizeof(bit)); for(int i=1;i<=n;++i) Add(i,1); for(int i=0;i<n;++i) { scanf("%d",&num); num++; printf("%d%c",Dic(1,n,num),i==n-1?' ':' '); } } return 0; }