BZOJ3033 太鼓达人 <欧拉回路>

Problem

太鼓达人

Time  Limit:  1  Sec\mathrm{Time\;Limit:\;1\;Sec}
Memory  Limit:  128  MB\mathrm{Memory\;Limit:\;128\;MB}

Description

七夕祭上,Vani\mathrm{Vani}牵着cl\mathrm{cl}的手,在明亮的灯光和欢乐的气氛中愉快地穿行。这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk\mathrm{XLk}Poet\mathrm{Poet}_shy\mathrm{shy}lydrainbowcat\mathrm{lydrainbowcat}拯救出来的的applepi\mathrm{applepi}。看到两人对太鼓达人产生了兴趣,applepi\mathrm{applepi}果断闪人,于是cl\mathrm{cl}拿起鼓棒准备挑战。然而即使是在普通难度下,cl\mathrm{cl}的路人本性也充分地暴露了出来。一曲终了,不但没有过关,就连鼓都不灵了。Vani\mathrm{Vani}十分过意不去,决定帮助工作人员修鼓。
鼓的主要元件是MM个围成一圈的传感器。每个传感器都有开和关两种工作状态,分别用1100表示。显然,从不同的位置出发沿顺时针方向连续检查KK个传感器可以得到MM个长度为KK0101串。Vani\mathrm{Vani}知道这MM0101串应该是互不相同的。而且鼓的设计很精密,MM会取到可能的最大值。现在Vani\mathrm{Vani}已经了解到了K的值,他希望你求出MM的值,并给出字典序最小的传感器排布方案。

Input

一个整数KK

Output

一个整数MM和一个二进制串,由一个空格分隔。表示可能的最大的MM以及字典序最小的排布方案,字符00表示关,11表示开。你输出的串的第一个字和最后一个字是相邻的。

Sample Input

1
3

Sample Output

1
8 00010111

Hint

得到的880101串分别是000000001001010010101101011011111111110110100100。注意前后是相邻的。长度为33的二进制串总共只有88种,所以M=8M=8一定是可能的最大值。
对于全部测试点,2K112\le K\le11

Source

Poetize2

标签:欧拉回路

Solution

k1k-1位二进制数看成点,kk位二进制数看成边,连接u,vu,v两点的边权就是(u<<1)v(u<<1)|v
例如k=4k=4时,边010101010\to 101的权为01010101,整个图如下:

(转载自 Clove_unique 的博客)
显然每个点的出度和入度均为22,一定存在欧拉回路,而欧拉回路一定会经过所有的边,即凑出所有kk位二进制数。于是第一问答案为2k2^k,第二问在图上找出字典序最小的欧拉回路即可。

Code

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
#include <bits/stdc++.h>
using namespace std;
template <class T> inline void read(T &x) {
x = 0; int c = getchar(), f = 1;
for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
int n, ans[2048]; bool mrk[2048];
bool DFS(int stp, int u) {
if (stp >= (1<<n)) return true;
int v = (u<<1)&((1<<n)-1);
if (!mrk[v]) {
mrk[v] = true;
if (DFS(stp+1, v))
return ans[stp] = 0, true;
mrk[v] = false;
}
v = (u<<1|1)&((1<<n)-1);
if (!mrk[v]) {
mrk[v] = true;
if (DFS(stp+1, v))
return ans[stp] = 1, true;
mrk[v] = false;
}
return false;
}
int main() {
read(n), DFS(0, 0), printf("%d ", 1<<n);
for (int i = 1; i < n; i++) putchar('0');
for (int i = 0; i <= (1<<n)-n; i++)
printf("%d", ans[i]);
return puts(""), 0;
}