Link
为了方便我们认为下标都是从\(0\)开始。
先进行特判,\(n=1\)时\(k=0\),\(n=2\)时无解。
考虑\(2\nmid n\)的情况,令\(p_{i,j}=j+2^i\bmod n\)即可。
若\(2|n\),在构造完上面的置换之后,发现置换一定会改变奇偶性。
若\(4|n\),再添加一组形如\((4i+2,4i,4i+1,4i+3,\cdots)\)的置换即可。
否则添加一组形如\((4i+2,4i,4i+1,4i+3,\cdots,n-2,n-1)\)和一组形如\((1,\cdots,n-5,n-2,n-4,n-1,n-3)\)的置换即可。
#include<cmath>
#include<cstdio>
#include<vector>
std::vector<std::vector<int>>ans;
int main()
{
int n;scanf("%d",&n);
if(n==2) return puts("-1"),0;else if(n==1) return puts("0"),0;
for(int i=0;i<ceil(log2(n/(n&1? 1:2)+1));++i)
{
std::vector<int>p(n);
for(int j=0;j<n;++j) p[j]=(j+(1<<i))%n;
ans.push_back(p);
}
if(~n&1)
{
std::vector<int>p(n);
for(int i=0;i+3<n;i+=4) p[i]=i+2,p[i+1]=i,p[i+2]=i+3,p[i+3]=i+1;
if(~n&2) ans.push_back(p);
else
{
p[n-2]=n-1,p[n-1]=n-2,ans.push_back(p);
for(int i=0;i+4<n;++i) p[i]=i;
p[n-4]=n-2,p[n-3]=n-4,p[n-2]=n-1,p[n-1]=n-3,ans.push_back(p);
}
}
printf("%d\n",(int)ans.size());
for(auto p:ans){for(int x:p)printf("%d ",x+1);puts("");}
}