[QOJ5434] Binary Substrings 题解
\(\text{[QOJ5434] Binary Substrings 题解}\)
有点意思的题目。
要我们求本质不同子串的个数最大,我们先思考满足这一条件时的情形。容易发现的是我们设 \(k\) 为满足 \(2^k+k-1\le n\) 最大的 \(k\),那么最终答案一定满足长度 \(\le k\) 的所有串均出现,\(>k\) 的所有串都不相同。
考虑所有长度是困难且无意义的,发现如果长度为 \(k\) 满足,那么所有长度 \(<k\) 的都满足;若长度为 \(k+1\) 的都满足,那么长度 \(>k+1\) 的都满足。那么只考虑 \(k\) 与 \(k+1\) 的情形。先只考虑满足长度为 \(k\) ,换句话说考虑 \(2^k+k-1=n\)。
由于需要构造方案,考虑有欧拉回路解决问题。建一张 \(2^k\) 个点的有向图,编号为 \([0,2^k)\),连边 \(x\to 2x\bmod 2^k\),\(x\to (2x+1)\bmod 2^k\),这个东西的实际意义就是每次增加串的长度,枚举选 \(0\) 还是选 \(1\)。那在这个图上跑一个哈密顿回路就构造了一个合法方案。
那在 \(n\le 10^6\) 的时候怎么跑一个哈密顿回路?答案是暴力 dfs 即可,总之跑得很快,或许这东西复杂度是线性的。
现在考虑 \(2^k+k-1<n\) 的情形。考虑原图每个点都有 \(2\) 条出边,\(2\) 条入边,跑出来环后还剩下的是 \(1\) 条出边,\(1\) 条入边,换句话说原图还剩下一堆环。那我们考虑把这些个小环拼到大环上去,由于每个点剩余的那条出边实际上是确定的,因此对于大环上每个点尝试拼接上小环,能全部拼上就全部拼上,拼不了就把对应的大环上那个点当作起点,绕一圈大环后走完后面的一部分即可。
代码略显抽象。
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 5;
int n, k, mod;
int a[N], cnt;
bool vis[N], fg;
void dfs(int x) {
a[++cnt] = x;
vis[x] = 1;
if (cnt == mod + 1) return fg = 1, void();
int y = (x << 1) & mod;
if (!vis[y]) {
dfs(y);
if (fg) return;
}
if (!vis[y | 1]) {
dfs(y | 1);
if (fg) return;
}
--cnt;
vis[x] = 0;
}
int nxt[N];
bool ins[N], yx[N];
int beh(int x) {
return x + 1 == cnt + 1 ? 1 : x + 1;
}
int main() {
cin >> n;
int k = 0;
while ((1 << (k + 1)) + k <= n) ++k;
mod = (1 << k) - 1;
dfs(0);
for (int i = 1; i <= cnt; i++) {
int x = a[i], y = (x << 1) & mod;
if (y != a[beh(i)]) nxt[x] = y;
else nxt[x] = y | 1;
}
int r = n - mod - k, key = 0;
for (int i = 1; i <= cnt; i++) {
int x = a[i], ct = 0;
if (ins[x]) continue;
while (!ins[x]) {
ins[x] = 1;
++ct;
x = nxt[x];
}
if (ct >= r) {
key = i;
break;
}
else yx[i] = 1, r -= ct;
}
for (int i = k - 1; i >= 0; --i) cout << ((a[beh(key)] >> i) & 1);
for (int i = key + 2; i <= cnt; i++) cout << (a[i] & 1);
for (int i = 1; i <= key; i++) {
if (key != cnt || i != 1) cout << (a[i] & 1);
if (!yx[i]) continue;
int x = a[i], y = x;
if (i == key) continue;
do {
y = nxt[y];
cout << (y & 1);
} while (x != y);
}
int x = a[key];
while (r--) {
x = nxt[x];
cout << (x & 1);
}
cout << "\n";
return 0;
}

浙公网安备 33010602011771号