```cpp
using namespace std;
inline ll read(){
ll x=0,o=1;char ch=getchar();
while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar();
if(ch==‘-‘)o=-1,ch=getchar();
while(ch>=‘0‘&&ch<=‘9‘)x=x10+ch-‘0‘,ch=getchar();
return xo;
}
const int N=25;
int visit[N];ll f[N][N][2];
inline void prework(){
f[1][1][0]=f[1][1][1]=1;
for(int i=2;i<=20;++i)
for(int j=1;j<=i;++j){
for(int k=j;k<=20;++k)f[i][j][0]+=f[i-1][k][1];
for(int k=1;k<=j-1;++k)f[i][j][1]+=f[i-1][k][0];
}
}
int main(){
prework();
int T=read();
while(T--){
memset(visit,0,sizeof(visit));
int n=read(),last,k;ll m=read();
for(int i=1;i<=n;++i){//考虑第一块木板
if(f[n][i][1]>=m){last=i;k=1;break;}
//一定要优先考虑f[n][i][1],因为我们要优先字典序最小,所以第一块k=1最好,则第二块是个低位
else m-=f[n][i][1];
if(f[n][i][0]>=m){last=i;k=0;break;}
else m-=f[n][i][0];
}
visit[last]=1;printf("%d",last);
for(int i=2;i<=n;++i){
k^=1;int j=0;
for(int len=1;len<=n;++len){
if(visit[len])continue;
++j;
if((k==0&&len<last)||(k==1&&len>last)){
if(f[n-i+1][j][k]>=m){last=len;break;}
else m-=f[n-i+1][j][k];
}
}
visit[last]=1;printf(" %d",last);
}
printf("\n");
}
return 0;
}
``
原文:https://www.cnblogs.com/PPXppx/p/11255466.html