传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6628
jc[i]表示 i的阶乘
ok[i+n]表示假设下一个位置的差值为 i 时 有多少方案数。
从p1(u=1)开始枚举,如果k>sum[i+n]*jc[n-1-u],那么说明这一位放i的话,后面的数字全排列的方案数还不够k的,那么直接减去,i=i+1。
vector<node> tmp表示当前枚举的情况下有哪些可能,由于只有枚举p1的时候会出现多种可能,枚举p2---pn-1的时候会情况不断减少,最后一定只剩一种情况就直接输出。
#include<bits/stdc++.h>
#define maxl 45
using namespace std;
int n;
long long k;
int p[maxl];
int ans[maxl];
long long jc[maxl];
int ok[maxl*2];
struct node
{
int a[maxl];
int in[maxl];
void init()
{
for(int i=0;i<=20;i++)
a[i]=0,in[i]=false;
}
};
vector <node> tmp;
vector <node> :: iterator it;
inline void prework()
{
scanf("%d%lld",&n,&k);
}
inline void solve(int u)
{
for(int i=1-n;i<=n-1;i++)
ok[i+n]=0;
bool flag;node d;
d.init();
if(u==1)
{
tmp.clear();
if(p[u]<0)
{
for(int i=n;i>=1-p[u];i--)
{
d.a[1]=i;d.a[2]=i+p[u];
d.in[i]=true;d.in[i+p[u]]=true;
for(int j=1;j<=n;j++)
if(!d.in[j])
ok[j-d.a[2]+n]++;
tmp.push_back(d);
d.in[i]=false;d.in[i+p[u]]=false;
}
}
else
{
for(int i=1;i<=n-p[u];i++)
{
d.a[1]=i;d.a[2]=i+p[u];
d.in[i]=true;d.in[i+p[u]]=true;
for(int j=1;j<=n;j++)
if(!d.in[j])
ok[j-d.a[2]+n]++;
tmp.push_back(d);
d.in[i]=false;d.in[i+p[u]]=false;
}
}
}
else
{
int x;
for(it=tmp.begin();it!=tmp.end();)
{
x=it->a[u]+p[u];
if(x<=n && x>0)
{ if( !(it->in[x]))
{
it->a[u+1]=x;
it->in[x]=true;
for(int j=1;j<=n;j++)
if(!(it->in[j]))
ok[j-x+n]++;
++it;
}
else
tmp.erase(it);
}
else
tmp.erase(it);
}
}
}
inline int abs(int x)
{
if(x<0) return -x;
else return x;
}
inline void dfs(int u,long long res)
{
long long t;
int sum;
for(int i=1-n;i<=n-1;i++)
if(ok[i+n])
{
sum=ok[i+n];
if(k<=sum*jc[n-1-u])
{
p[u]=i;
solve(u);
if(u<n-1)
dfs(u+1,k);
return;
}
k-=sum*jc[n-1-u];
}
}
inline void mainwork()
{
for(int i=1-n;i<=n-1;i++)
ok[i+n]=n-abs(i);
ok[0+n]=0;
tmp.clear();
dfs(1,k);
}
inline void print()
{
it=tmp.begin();
for(int i=1;i<=n;i++)
printf("%d%c",it->a[i],(i==n)?'\n':' ');
}
int main()
{
jc[0]=1;jc[1]=1;
for(int i=1;i<=20;i++)
jc[i]=jc[i-1]*i;
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}