LY1153 [ 20230317 CQYC省选模拟赛 T3 ] 灵能潮汐
题意
给定一个长度为 \(n\) 的字符串 \(s\)。
让你确定一个答案 \(x\),使得 \(x + i - 1\) 的十进制上有 \(s_i\)。
Sol
不难想到考虑从低往高位讨论,讨论当前这位选的数字是多少。
对于这 \(n\) 个限制,将 \(x + i - 1 = s_i\) 的限制删掉。
发现如果将每相邻 \(10\) 个限制合并,高一位的限制依然满足连续,依然可以使用相同的方法合并,注意到总状态为 \(10 ^ {log_10 ^ {n}} = n\)。
总复杂度:\(O(n \log n)\)
Code
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <vector>
#define ll long long
#define il inline
#define rg register
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;
#endif
il int read() {
rg int p = 0, flg = 1;
rg char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') flg = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
p = p * 10 + c - '0';
c = getchar();
}
return p * flg;
}
il string read_() {
rg string ans;
rg char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
ans += c, c = getchar();
return ans;
}
il void write(ll x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x > 9) {
write(x / 10);
}
putchar(x % 10 + '0');
}
const int N = 1e6 + 5;
array <int, N> ksl;
il ll divide(vector <int> &isl, bool flg) {
if (isl.size() == 1) {
int cnt = 0;
for (rg int i = 0; i <= 9; i++)
if (isl.front() & (1 << i))
cnt++, ksl[cnt] = i;
if (!cnt) return !flg;
if (cnt == 1 && !ksl[1]) return 10;
if (cnt == 1) return ksl[1];
if (!ksl[1]) swap(ksl[1], ksl[2]);
rg int res = 0;
for (int i = 1; i <= cnt; i++) res = res * 10 + ksl[i];
/*
rg vector <int> tp;
if (tp.empty()) return !flg;
if (tp.size() == 1 && !tp.front()) return 10;
if (tp.size() == 1) return tp.front();
if (!tp.front()) swap(tp[0], tp[1]);
*/
return res;
}
if (flg && !isl.front()) {
rg bool tp = 1;
for (rg int i = 1; i < (int)isl.size(); i++) {
rg int k = i, tp0 = 0;
while (k) tp0 |= 1 << (k % 10), k /= 10;
if (isl[i] != (isl[i] & tp0)) {
tp = 0;
break;
}
}
if (tp) return 0;
}
rg ll ans = 2e18;
for (rg int i = 0; i <= 9; i++) {
if (isl.size() == 2 && i == 9 && (isl[0] & ~(1 << 9)) == isl[0] && (isl[1] & ~1) == isl[1]) continue;
rg vector <int> tp;
rg int tp0 = 0, tp1 = i;
for (rg int j = 0; j < (int)isl.size(); j++) {
/* cnt++; */
if (tp1 == 10) {
tp.push_back(tp0);
tp0 = tp1 = 0;
}
tp0 |= isl[j] & ~(1 << tp1), tp1++;
}
tp.push_back(tp0);
ans = min(ans, divide(tp, i > 0) * 10 + i);
}
return ans;
}
il void solve() {
rg int n = read();
rg string str = read_();
rg vector <int> isl;
for (rg auto k : str)
isl.push_back(1 << (k - '0'));
write(divide(isl, 0)), puts("");
}
signed main() {
/* freopen("pulse.in", "r", stdin); */
/* freopen("pulse.out", "w", stdout); */
rg int T = read();
while (T--) solve();
/* cerr << cnt << endl; */
return 0;
}