Контест, к которому написан разбор
[problem:280726A]
В задаче необходимо найти минимальное расстояние между двумя одинаковыми элементами цикличной строки.
Запоминаем первое и последнее вхождения символов и вычисляем минимальное расстояние между одинаковыми символами как $$$ans = min(i-prev[c],n+first[c]-i)$$$ , где $$$c$$$ — символ, $$$i$$$ — текущее положение символа, $$$prev[c]$$$ — последнее вхождение символа, $$$first[c]$$$ — первое вхождение.
Из всех таких расстояний берем минимум и выводим ответ $$$(ans \cdot 33 +59) \; / \; 60$$$
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
int n;
cin >> n;
int ans = n;
vector <int> prev(26, -1), first(26, -1);
for (int i = 0; i < n; i++) {
char c;
cin >> c;
if (first[c - 'a'] == -1 ) first[c - 'a'] = i;
else ans = min(ans, min(i - prev[c - 'a'], n + first[c - 'a'] - i));
prev[c - 'a'] = i;
}
cout << (ans * 33 + 59) / 60;
}
[problem:280726B]
Немного преобразуем уравнение
Учитывая ограничения задачи, ответом будем являться количество различных разложений $$$\cfrac{A-Y}{B-X}$$$.
Пусть $$$\cfrac{a}{b}$$$ — сокращенная дробь от $$$\cfrac{A}{B}$$$, тогда $$$\forall k \in [1 \ldots gcd(A,B)] \; \; \; k \cdot \cfrac{a}{b} = \cfrac{A}{B}$$$
Если $$$X=Y=0$$$, то тогда таких значений $$$gcd(A,B)$$$, но такого быть не может, поэтому ответ $$$gcd(A,B)-1$$$.
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
int n;
cin >> n;
while (n--) {
long long a, b;
cin >> a >> b;
cout << __gcd(a, b) - 1 << endl;
}
}
[problem:280726C]
Нам не важно в какую сторону идти, поэтому будем двигаться вправо и при $$$0 < x$$$ можно взять $$$x = |x|$$$.
Количество шагов не может быть меньше, чем $$$ step = \sqrt{x}$$$, так как сумма всех шагов равна $$$sum =\cfrac{ (step+1) \cdot step }{2}$$$. Пока $$$ sum < x$$$, будем увеличивать $$$step$$$, как только $$$sum \geq x$$$, продолжаем увеличивать $$$step$$$, пока $$$ ( sum - x) \; mod \; 2 = 1$$$, потому что нам нужно попасть в $$$x$$$, а значит из точки $$$sum$$$ сделать какие-то шаги( которые мы уже делали) влево два раза, то есть $$$step back = (sum - x) \; / \; 2$$$.
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
int x;
cin >> x;
x = abs(x);
int step = sqrt(x), sum = (step + 1 ) * step / 2;
while (sum < x || (sum - x) % 2 == 1) {
step++;
sum += step;
}
cout << step;
}
[problem:280726D]
Если у героя есть ключ от двери, то можно считать эту дверь как поле, в которое можно пойти, в противном случае можно сказать, что эта дверь — стена.
Таким образом достаточно перебрать всевозможные варианты комбинации ключей (их можно получить рекурсивным полным перебором, всего различных вариантов 16) и выбрать среди них такой, что сумма стоимости ключей будет минимальна. Если из лабиринта никак нельзя выбраться, то вывести $$$Unreal$$$.
Для поиска пути можно воспользоваться поиском в ширину или глубину (почитать о них можно здесь — DFS, BFS)
#include <bits/stdc++.h>
using namespace std;
size_t xS, yS;
size_t xE, yE;
int step[4] = {0, 1, 0, -1};
bool dfs(size_t x, size_t y, const string& s,
vector<vector<char>>& lab, vector<vector<bool>>& used) {
if (used.size() <= x || used.size() <= y ||
used[x][y] || (s.find(lab[x][y]) == string::npos))
return false;
used[x][y] = true;
if (x == xE && y == yE)
return true;
size_t next_x, next_y;
bool path = false;
for (int i = 0; i < 4; i++) {
next_x = x + step[i];
next_y = y + step[(i + 1) % 4];
path |= dfs(next_x, next_y, s, lab, used);
}
return path;
}
int solve(string s, int sum,
vector<vector<char>>& lab,
vector<vector<bool>>& used,
vector<int>& door) {
used.assign(lab.size(), vector<bool>(lab.size(), false));
int ans = 5000;
if (dfs(xS, yS, s, lab, used)) {
ans = min(ans, sum);
}
for (char c = '1'; c <= '4'; c++) {
if (s[s.size() - 1] < c)
ans = min(ans, solve(s + c, sum + door[c - '1'], lab, used, door));
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
int n;
cin >> n;
vector<int> door(4);
for (int i = 0; i < 4; i++) {
cin >> door[i];
}
vector<vector<char>> lab(n, vector<char>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> lab[i][j];
if (lab[i][j] == 'S') {
xS = i;
yS = j;
}
if (lab[i][j] == 'E') {
xE = i;
yE = j;
}
}
}
vector<vector<bool>> used;
int ans = solve("SE.", 0, lab, used, door);
if (ans == 5000)
cout << "Unreal";
else
cout << ans;
}
[problem:280726E]
Пусть $$$a,b$$$ — первое и второе названия организаций. Вычислим $$$Z$$$-функцию ( подробнее о ней можно почитать здесь) для строки $$$a+?+b$$$. Теперь по результаты $$$Z$$$-функции есть 3 варината развития событий:
Строка $$$a$$$ является подстрокой $$$b$$$. Ответом будет строка $$$b$$$, где первый символ первого вхождения $$$a$$$ будет заглавным.
Объединяем строки, где общей частью будет максимальный суффикс $$$b$$$, который является префиксом $$$a$$$ (первый символ общей части является заглавной буквой).
Строка $$$a$$$ не является подстрокой $$$b$$$ и нет такого суффикса $$$b$$$, который являлся бы префиксом $$$a$$$, тогда ответом будет строка $$$b+a$$$.
Аналогичным образом поступаем с $$$Z$$$-функцией строки $$$b+?+a$$$ и среди всех результатов выводим минимальный.
Решение AmDer
#include <bits/stdc++.h>
using namespace std;
void z_function(string s, vector<size_t>& zf) {
for_each(s.begin(), s.end(), [](char & c){
c = ::toupper(c);
});
for (size_t i = 1, l = 0, r = 0; i < s.size(); i++) {
if (i <= r)
zf[i] = min(r - i + 1, zf[i - l]);
while (s[zf[i]] == s[i + zf[i]] && zf[i] + i < zf.size())
zf[i]++;
if (zf[i] + i - 1 > r)
l = i, r = i + zf[i] - 1;
}
}
void solve(string& a, string& b, string& res) {
size_t n = a.size() + b.size() + 1;
vector<size_t> zf(n);
z_function(a + '?' + b, zf);
res = b + a;
for (size_t i = a.size() + 2; i < n; i++) {
if (n - i == zf[i]) {
res = b.substr(0, i - a.size() - 1) + a;
break;
}
else if (zf[i] == a.size()) {
res = b.substr(0, i - a.size() - 1) + a + b.substr(i - 1);
break;
}
}
}
int main() {
ios::sync_with_stdio(false);
string a, b;
cin >> a >> b;
string res1, res2;
solve(a, b, res1);
solve(b, a, res2);
if (res1.size() == res2.size())
cout << min(res1, res2);
else
cout << (res1.size() > res2.size() ? res2 : res1);
}