Link
为了方便我们认为下标都是从(0)开始。
先进行特判,(n=1)时(k=0),(n=2)时无解。
考虑(2
mid n)的情况,令(p_{i,j}=j+2^imod 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
",(int)ans.size());
for(auto p:ans){for(int x:p)printf("%d ",x+1);puts("");}
}