VP Educational Codeforces Round 70 (Rated for Div. 2)
A. You Are Given Two Binary Strings...
题意:给你两个二进制串\(x, y\),要求把\(y\)左移\(k\)位后和\(x\)相加然后翻转后的二进制串在字典序下最小,求最小的\(k\)。
为了让翻转后二进制字典序最小,应该让低位尽可能是零,那么应该人\(y\)的最低的\(1\)和\(x\)中一个\(1\)相加。找可以和它相加的最近的那个\(1\)位置。看要位移几位。
点击查看代码
void solve() {
std::string s, t;
std::cin >> s >> t;
std::ranges::reverse(s);
std::ranges::reverse(t);
int p = t.find('1');
std::vector<int> pos;
for (int i = 0; i < s.size(); ++ i) {
if (s[i] == '1') {
pos.push_back(i);
}
}
auto it = std::ranges::lower_bound(pos, p);
std::cout << std::abs(*it - p) << "\n";
}
B. You Are Given a Decimal String...
题意:对于一个\(x, y\),你只能每次加上\(x\)或\(y\)。然后当前和的个位数会被打印出来。你被给出一个打印序列,求对于每个\(x, y\)最少插入几个字符可以满足条件。
其它就是求在限定\(x, y\)的情况下,从个位数位\(x\)加到个位数变成\(y\)需要加几次。可以用\(bfs\)求。
点击查看代码
void solve() {
std::string s;
std::cin >> s;
auto get = [&](int x, int y) -> int {
std::array<std::array<int, 10>, 10> d{};
for (int i = 0; i < 10; ++ i) {
for (int j = 0; j < 10; ++ j) {
d[i][j] = -1;
}
}
for (int i = 0; i < 10; ++ i) {
std::queue<int> q;
q.push((i + x) % 10);
d[i][(i + x) % 10] = 0;
q.push((i + y) % 10);
d[i][(i + y) % 10] = 0;
while (q.size()) {
int u = q.front(); q.pop();
if (d[i][(u + x) % 10] == -1) {
d[i][(u + x) % 10] = d[i][u] + 1;
q.push((u + x) % 10);
}
if (d[i][(u + y) % 10] == -1) {
d[i][(u + y) % 10] = d[i][u] + 1;
q.push((u + y) % 10);
}
}
}
int res = 0;
for (int i = 0; i + 1 < s.size(); ++ i) {
if (d[s[i] - '0'][s[i + 1] - '0'] == -1) {
return -1;
}
res += d[s[i] - '0'][s[i + 1] - '0'];
}
return res;
};
for (int i = 0; i < 10; ++ i) {
for (int j = 0; j < 10; ++ j) {
std::cout << get(i, j) << " \n"[j == 9];
}
}
}
C. You Are Given a WASD-string...
题意:给你四个方向的移动序列。记移动中\(max_x, min_x, max_y, min_y\)分别为到的最大最小的\(x, y\)下标,那么代价为\((max_x - min_x + 1) \times (max_y - min_y + 1)\)。你现在可以最多插入一个移动,求最小代价。
行和列可以分开考虑。
考虑行怎么做,列同理。我们希望\(max_x\)可以减少\(1\),或者\(min_x\)可以增大\(1\)。直接加减是不对的,因为你需要进行一次相反操作,这可以使得另一个最值变化。但想要使得最大值变小或者最小值变大,肯定是在它第一次达到的位置操作,那么可以对每个情况模拟。
点击查看代码
void solve() {
std::string s;
std::cin >> s;
i64 maxx = 0, minx = 0, maxy = 0, miny = 0;
i64 maxx1 = 0, minx1 = 0, maxy1 = 0, miny1 = 0;
i64 maxx2 = 0, minx2 = 0, maxy2 = 0, miny2 = 0;
i64 x = 0, y = 0;
for (auto & c : s) {
if (c == 'W') {
-- x;
} else if (c == 'S') {
++ x;
} else if (c == 'D') {
++ y;
} else {
-- y;
}
maxx = std::max(maxx, x);
minx = std::min(minx, x);
maxy = std::max(maxy, y);
miny = std::min(miny, y);
}
bool flagx1 = true, flagx2 = true, flagy1 = true, flagy2 = true;;
x = 0, y = 0;
for (auto & c : s) {
if (c == 'W') {
-- x;
} else if (c == 'S') {
++ x;
} else if (c == 'D') {
++ y;
} else {
-- y;
}
if (x == maxx && flagx1) {
flagx1 = false;
-- x;
minx1 = std::min(minx, x - 1);
}
maxx1 = std::max(maxx1, x);
minx1 = std::min(minx1, x);
}
x = 0, y = 0;
for (auto & c : s) {
if (c == 'W') {
-- x;
} else if (c == 'S') {
++ x;
} else if (c == 'D') {
++ y;
} else {
-- y;
}
if (x == minx && flagx2) {
flagx2 = false;
++ x;
maxx2 = std::max(maxx, x + 1);
}
maxx2 = std::max(maxx2, x);
minx2 = std::min(minx2, x);
}
x = 0, y = 0;
for (auto & c : s) {
if (c == 'W') {
-- x;
} else if (c == 'S') {
++ x;
} else if (c == 'D') {
++ y;
} else {
-- y;
}
if (y == maxy && flagy1) {
flagy1 = false;
-- y;
miny1 = std::min(miny, y - 1);
}
maxy1 = std::max(maxy1, y);
miny1 = std::min(miny1, y);
}
x = 0, y = 0;
for (auto & c : s) {
if (c == 'W') {
-- x;
} else if (c == 'S') {
++ x;
} else if (c == 'D') {
++ y;
} else {
-- y;
}
if (y == miny && flagy2) {
flagy2 = false;
++ y;
maxy2 = std::max(maxy, y + 1);
}
maxy2 = std::max(maxy2, y);
miny2 = std::min(miny2, y);
}
i64 lenx = maxx - minx + 1, leny = maxy - miny + 1;
i64 lenx1 = maxx1 - minx1 + 1, leny1 = maxy1 - miny1 + 1;
i64 lenx2 = maxx2 - minx2 + 1, leny2 = maxy2 - miny2 + 1;
i64 ans = std::min({lenx1 * leny, lenx * leny1, lenx2 * leny, lenx * leny2, lenx * leny});
std::cout << ans << "\n";
}
D. Print a 1337-string...
题意:构造一个长度不超过\(1e5\)且有\(n\)个\(1337\)作为子序列的字符串。
考虑左边一个\(1\),中间\(m\)个\(3\),右边一个\(7\),那么有\(\frac{m(m-1)}{2}\)个\(1337\)。我们找到最接近\(n\)的这个数,然后在\(133\)后面插入\(n - \frac{m(m-1)}{2}\)个\(7\)就行。
点击查看代码
void solve() {
int n;
std::cin >> n;
i64 m = 1;
while (m * (m - 1) / 2 <= n) {
++ m;
}
-- m;
std::string ans;
ans += "133";
ans += std::string(n - m * (m - 1) / 2, '7');
ans += std::string(m - 2, '3');
ans += '7';
std::cout << ans << "\n";
}