正题
大意
一个数K,求一个最长的01环形序列(头和尾相连),使得每个长度为k的连续子序列都不相同。(要输出这个串,如果有多个答案输出字典序最小的)
解题思路
尝试将长度为k的01序列全排列一下我们会发现总共有2n2n种排列,那么其实这个序列长度很明显就是2n2n。然后我们开始想一想如何输出队列。
首先每个序列只能也必须出现一次,而每个序列后面都可以接上某些序列,而最后又得回到最开始的序列。这么一看,其实很像欧拉回路。所以我们可以用欧拉回路来求,将每个排列作为一个点,然后可以相接的连边。
连边方式:
首先我们可以发现其实这个排列可以连接的下一个排列只有两种情况,就是将k∼2k∼2的数取出来,然后在末尾加入一个0/10/1。
之后暴力欧拉回路
代码
#include<cstdio>
#include<algorithm>
#define K 2060
using namespace std;
int ans[K],n,k,m;
bool v[K];
bool euler(int x,int y)//求欧拉回路
{if (v[x]) return 0;ans[y]=x&1;//取二进制第一位v[x]=true;//标记if (y==n) return 1;if (euler((x<<1)&m,y+1)) return 1;//按字典序小的开始搜索if (euler(((x<<1)|1)&m,y+1)) return 1;//搜索v[x]=false;//回溯
}
int main()
{scanf("%d",&k);n=1<<k;m=n-1;printf("%d ",n);euler(n-2,1);//从n-2位保证输出的时候前面k个都是0for (int i=1;i<=n;i++)printf("%d",ans[i]);
}