题目描述
七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行。这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk、Poet_shy和lydrainbowcat拯救出来的的applepi。看到两人对太鼓达人产生了兴趣,applepi果断闪人,于是cl拿起鼓棒准备挑战。然而即使是在普通难度下,cl的路人本性也充分地暴露了出来。一曲终了,不但没有过关,就连鼓都不灵了。Vani十分过意不去,决定帮助工作人员修鼓。
鼓的主要元件是M个围成一圈的传感器。每个传感器都有开和关两种工作状态,分别用1和0表示。显然,从不同的位置出发沿顺时针方向连续检查K个传感器可以得到M个长度为K的01串。Vani知道这M个01串应该是互不相同的。而且鼓的设计很精密,M会取到可能的最大值。现在Vani已经了解到了K的值,他希望你求出M的值,并给出字典序最小的传感器排布方案。
Solution
根据样例,我们可以得到如下结论:
- 第一问的答案是 2 k 2^k 2k,因为可以由0~ 2 k − 1 2^k-1 2k−1组合而成最终的数列。
- 一串数列的开头是000…即若干个0.
对于若干个0,很难做到有效的去重,因此我们只需要以第一位为0,根据环形的特点最后往末尾补0即可。
举一个通俗的例子:
00010111这个数字,以0开头,枚举的数是01011100,而这两个数的本质是相同的,因此只需要最后输出的时候处理即可。
接下来的问题就是搜索,如何搜索呢?
- 如果当前数字已经重复,则不继续往下做
- 如果长度超过m,则不继续往下做
- 记录答案
- 进一步搜索
- 回溯,撤销答案
注意搜索时,若当前数字为num,下一步数字应为num<<1和num<<1|1,表示在尾部加一个0或1.
但是这些数字要做and运算,防止数字过大造成RE。
#include<bits/stdc++.h>
using namespace std;
int k,m;
int v[10000000];
int ans[10000];
int dfs(int num,int deep)
{if (v[num]==1) return 0;//若当前数被枚举到if (deep==m) return 1;v[num]=1;ans[deep]=num & 1; if (dfs((num<<1)&(m-1),deep+1)) return 1;if (dfs((num<<1|1)&(m-1),deep+1)) return 1;v[num]=0;return 0;
}
int main(void)
{cin>>k;m=1<<k;cout<<m<<' ';dfs(0,1); for (int i=1;i<k;++i) cout<<0;for (int i=1;i<=m-k+1;++i) cout<<ans[i];return 0;
}