题意
传送门 AcWing 400 太鼓达人
题解
长度为 K K K 的 01 01 01 串共有 2 K 2^K 2K 种,需尽可能多地通过环上的顺时针移动,遍历不同的 01 01 01 串,并返回初始串。将 K K K 长的 01 01 01 串看做边,权值为 01 01 01 串的最后一位数字,将出边代表的 01 01 01 串的 K − 1 K-1 K−1 长前缀看做点。每个点各有 2 2 2 条出边与入边,则存在有向图的欧拉回路。以点 0 0 0 为起点求解欧拉回路,为保证字典序最小,贪心地从权值较小的边开始递归。总时间复杂度 O ( 2 K ) O(2^K) O(2K)。
#include <bits/stdc++.h>
using namespace std;
const int maxk = 12, maxn = 1 << maxk, maxm = maxn << 1;
int K, nr, res[maxn];
int tot, head[maxn], to[maxm], nxt[maxm], cost[maxm];
bool vs[maxn];
inline void add(int x, int y, int z)
{
to[++tot] = y, cost[tot] = z, nxt[tot] = head[x], head[x] = tot;
}
void euler(int x)
{
for (int &i = head[x], y, z; i;)
{
y = to[i], z = cost[i], i = nxt[i];
euler(y);
res[++nr] = z;
}
}
int main()
{
scanf("%d", &K);
int t = 1 << (K - 1);
for (int i = 0; i < t; ++i)
{
int j = (i << 1) & (t - 1);
add(i, j | 1, 1), add(i, j, 0);
}
euler(0);
printf("%d ", 1 << K);
for (int i = 1; i < K; ++i)
putchar('0');
while (nr >= K)
putchar(res[nr--] + '0');
putchar('\n');
return 0;
}