发布于 

DeBruijin

DeBruijin

hdu 2894

题目来源: hdu

分析

题目要求,给出一个长度为$k ( 2 k ) $,我们需要生成一个0,1组成的最长环形字符串,使得其中任意k个连续的子串互不相等。题目要求输出该字符串长度与字符串本身。

我们在求字符串之前,可以先看一下它的长度有什么规律。我们可以证出长度$ m = 2^k $。因为长度为k01字符串一共存在\(2^k\)中情况,而\(m=2^k\)时它也有\(2^k\)个子串,所以我们只需要让每一个子串各不相同就好了。

然后我们只需要较为暴力的求出该串即可。我这里使用的时深搜的方法。因为每个字串的下一个相邻的子串只有两种情况,我们搜索一下,看哪一种最后能够将所以子串生成出来即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstring>

using namespace std;

int dist[100100];
int n,k;

bool dfs(int x)
{
if (dist[x]==n)
return true;

for (int i = 0; i<2; i++)
if (dist[(x*2+i)%n]==0)
{
dist[(x*2+i)%n] = dist[x] + 1;
if (dfs((x*2+i)%n))
return true;
dist[(x*2+i)%n] = 0;
}

return false;
}

int trans(int x)
{
int t = n/2;
return x/t;
}

int main()
{
while (cin >> k)
{
n = pow(2,k);
cout << pow(2,k) << " ";

dist[0] = 1;
memset(dist,0,sizeof(dist));

dfs(0);

int t = 0;
cout << trans(t);
for (int i = 1; i<n; i++)
for (int j = 0; j<2; j++)
if (dist[(t*2+j)%n]==dist[t]+1)
{
t = t*2 + j;
t %= n;
cout << trans(t);
}
cout << endl;
}
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Songer](https://blog.songer.xyz/) 创建,使用 Stellar 作为主题。