Codeforces Round #692 (Div. 2, based on Technocup 2021 Elimination Round 3)
Codeforces Round #692 (Div. 2, based on Technocup 2021 Elimination Round 3)
从传智杯到牛客到cf, 一条龙, 脑子有点呆
A - In-game Chat
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> s + 1;
int c = 0;
per (i, n, 1) if (s[i] == ')') ++c; else break;
cout << (c * 2 > n ? "YES\n" : "NO\n");
}
return 0;
}
B - Fair Numbers
1~9的公倍数为2520, 故最多检测2519个数, 就能找到最小的公平数
bool check(ll x) {
ll y = x;
while (x) {
if (x % 10 == 0) { x /= 10; continue; }
if (y % (x % 10)) return 0;
x /= 10;
}
return 1;
}
int main() {
IOS;
for (cin >> _; _; --_) {
ll n; cin >> n;
for (ll i = n; i <= 1e18; ++i)
if (check(i)) { cout << i << '\n'; break; }
}
return 0;
}
C - Peaceful Rooks
按理来说每个数(不在对角线上的)移动一次刚刚好
但是他要就不能相互攻击, 有的就要先让出个位置了, 比如 (2, 3), (3, 4) (4, 2)
成了个环, 要先有个点到其他位置呆着所以总步数 +1
就用并查集判有多少个环就行了
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> m;
rep (i, 1, n) f[i] = i;
ll ans = 0;
rep (i, 1, m) {
int x, y; cin >> x >> y;
if (x == y) continue; ++ans;
x = find(x), y = find(y);
if (x == y) ++ans;
else f[y] = x;
}
cout << ans << '\n';
}
return 0;
}
D - Grime Zoo
当?序列为 111..000 or 000...111 or 00..00 or 11..11 时最小
不存在 01, 10相间, 这个证明有点费事, 就整个不能 0101的把 不能 11000011000的自己证吧
对于 ..?..?.?.?.. 问号(这四个问号在是相邻的)对应 0101, 记 st[i][0, 1, 2] 表示从1~i中有多少个 0, 1, ?, ed[i][0,1,2] 同理
0101 下标分别为 a, b, c, d 且 a < b < c < d, 序列总长为n
对于b和c贡献为 st[b][0] * x + ed[b][0] * y + st[c][1] * y + ed[c][1] * x
将序列变为 0001 bc的贡献为: (st[b][1] - 1(b变成0了-1)) * x + (ed[b][1] - 1) * y + (st[c][1] - 1) * y + (ed[c][1] - 1) * x
不论变成 0001 还是 0111 都比 0101 要小, 当然肉眼也可见,
想想也因该发现 00000, 1111最小毕竟为0, 但是我们能改的位置有限, 记我们只能改 问号为 1 or 0
抛弃不能改的位置也理应是 00000, 1111是最小, 但还要考虑 不能改的位置那只好妥协成了 00001111.. or 11111000.. or 00000.. or 111..
int main() {
IOS; ll x, y; cin >> s >> x >> y;
rep (i, 1, s.size()) rep (j, 0, 2)
st[i][j] = st[i - 1][j] + (j < 2 ? s[i - 1] == '0' + j : s[i - 1] == '?');
per (i, s.size(), 1) rep (j, 0, 2)
ed[i][j] = ed[i + 1][j] + (j < 2 ? s[i - 1] == '0' + j : s[i - 1] == '?');
int cnt0 = 0, cnt1 = 0;
ll t = 0, res, ans;
rep (i, 1, s.size())
if (s[i - 1] == '0') ++cnt0, t += cnt1 * y;
else ++cnt1, t += cnt0 * x;
res = ans = t;
rep (i, 1, s.size()) if (s[i - 1] == '?') {
res -= (st[i - 1][0] + st[i - 1][2]) * x + ed[i + 1][0] * y;
res += st[i - 1][1] * y + (ed[i + 1][1] + ed[i + 1][2]) * x;
umin(ans, res);
} res = t;
per (i, s.size(), 1) if (s[i - 1] == '?') {
res -= st[i - 1][0] * x + (ed[i + 1][0] + ed[i + 1][2]) * y;
res += (st[i - 1][1] + st[i - 1][2]) * y + ed[i + 1][1] * x;
umin(ans, res);
}
cout << ans;
return 0;
}