Gym 102586I Amidakuji

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("");}
}

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/12796925.html