When submitting a solution in C++, please select either C++14 (GCC 6-32) or C++17 (GCC 7-32) as your compiler. ×

pkhaustov's blog

By pkhaustov, 13 years ago, In Russian
Задача A. Футбол
Классическая задача A второго дивизиона. Можно было решить без хранения в памяти всех N строк входного файла. Хотя тесты проходило и любое решение, которое только можно себе представить.
Решение без сохранения всех N строк в памяти: считывать все строки, при встрече незнакомой строки присваивать ей идентификатор. Для каждого идентификатора завести счетчик, который будет отражать, сколько раз строка встретилось во входном файле. Из двух строк выбрать ту, у которой значение счетчика больше.

Задача B. Письмо
Самое простое решение - это для каждой буквы (другие символы просто игнорировать) в обеих строках посчитать число ее вхождений. Если какая-то буква входит во вторую строку большее число раз, чем входит в первую, ответ "NO", иначе ответ "YES". Очевидная асимптотика решения O(L), где L - ограничение на длину строки во входном файле.

Задача С. Счастливые билеты
Всем известно условие делимости числа на 3: "Число кратно трем, тогда и только тогда, когда сумма цифр этого числа делится без остатка на 3". Соответственно, чтобы при склеивании двух чисел получить число кратное трем, необходим чтобы сумма цифр первого числа плюс сумма цифр второго числа было кратно трем.
Стоит отметить, что оперировать в условиях этой задачи можно только с остатками от деления на 3. Несложно понять, что есть смысл соединять числа, которые дают в остатке от деления на 3 двойку с теми, кто дает в остатке единицу. Числа, которые нацело делятся на 3 можно объединять только с числами, которые так же делятся нацело на 3. Если посчитать количество чисел на кусках билетов с остатком от деления на 3 равным 0, 1, 2 (обозначим их как R0, R1, R2 соответственно), то ответом будет min(R1, R2) + [R0 / 2]. Здесь [] - операция округления в меньшую сторону.

Задача D. Путешествие
Задача не требует знания каких-то алгоритмов, математики или даже банальной логики. От Вас требуется найти все частные случаи и не забыть рассмотреть каждый из них.
Теста "1 1" быть не могло (ограничения такие).
Для тестов "1 2" и "2 1" ответом служит последовательность из трех клеток (1 1, оставшаяся клетка, 1 1). Телепортов не требуется.
Для тестов "1 M" и "N 1" (2 < N, M) ответом служит последовательность 1 1 -> 1 2 -> ... -> 1 M (ну и аналогично для перевернутого случая) и снова 1 1 в конце. Требуется один телепорт (1 M -> 1 1).
Далее логика простая. Если хотя бы одна из сторон - четная, то пройти можно следующим алгоритмом:
Рассмотрим случай, когда количество строк нечетно. При нечетном количестве столбцов можно действовать так же, поменяв строки и столбцы местами.
Из клетки 1 1 шагнем в 1 2 и далее пойдем змейкой по прямоугольнику Rect(1, 2, N, M). То есть во время обхода змейкой не посещаем первую строку. Такой обход закончится в клетке с координатами 2 M. После чего можно шагнуть на 1 M и спокойно прийти по первой строке в 1 1.
Для случая, когда N и M четные, можно воспользоваться тем же алгоритмом. Очевидно, что телепортов строить во всех этих случая не потребуется.
Для случая, когда N и M нечетные всегда потребуется один телепорт. Если действовать по той же стратегии, то в конце обхода змейкой можно попасть только в клетку с координатами N M, откуда необходимо телепортироваться в клетку 1 M и пройтись по первой строке до клетки 1 1.

Задача E. Гонка
Задача не требует знания каких-то сложных формул из физики. Сразу открою занавесу и выпишу все формулы, которые потребуются при решении.
X0 = 0
Xn + 1 = Xn + Vn (Tn+1 - Tn), где Xi - координата, Ti - момент времени
Несложно понять, что решение с асимптотикой O(SN2) получит заслуженный Time Limit. Решение с асимптотикой O(KN3) вполне сойдет. Впрочем, скорее всего существует решение с гораздо более хорошей трудоемкостью.
Далее будет рассказано решение за O(KN3), которое имеет множество других достоинств.
Будем рассматривать всю гонку, как набор некоторых событий упорядоченных во времени. События - изменение скорости какого-либо участника в какой-либо момент времени. Для каждого участника несложно (еще при чтении) получить все события, которые с ним связаны. Каждое из них обладает двумя параметрами: время, когда была сменена скорость и сама величина скорости. Все события можно объединить и упорядочить хронологически (в порядке неубывания времени, когда происходит событие).
Теперь нет смысла идти по всем моментам времени (от 0 до S). Есть смысл рассматривать только моменты времени, в которые происходит хотя бы одно событие. Всего смен скоростей будет O(NK). Для дальнейшего решения можно сделать несколько утверждений:
Между двумя соседними моментами времени (в которые происходят события) скорости автомобилей остаются постоянными. Соответственно, автомобиль i обгонит на участке между этими двумя моментами времени автомобиль j если Vi > Vj (иначе обгон точно не возможен). А далее требуется соблюдение одного из двух условий:
  • Координата автомобиля i в первый момент времени меньше, чем у автомобиля j, а во второй момент времени координата автомобила i уже больше координаты автомобиля j.
  • Координата автомобиля i в первый момент времени такая же, как у автомобиля j, а во второй момент координата автомобиля i больше координаты автомобиля j. При этом на предыдущем этапе координата автомобиля i была меньше (то есть он сравнялся с автомобилем j на прошлом интервале времени).
На каждом временном интервале можно за O(N2) проверять для каждой пары (i, j) обгоняет ли автомобиль i автомобиль j.
Каждое из вышеописанных условий можно проверить в целых числах (32 бита вполне хватает). Ответ так же не потребует 64-битовой переменной.
Стоит отметить, что решение не использует значение S, которое дается во входном файле.  Дописав один IF можно получить решение, которое будет правильно обрабатывать даже случаи, когда автомобили некоторое время ехали бок о бок.
  • Vote: I like it
  • +5
  • Vote: I do not like it