Блог пользователя Kenny_HORROR

Автор Kenny_HORROR, 15 лет назад, По-русски
Div 2. Задача А. Cifera
Если переформулировать задачу то необходимо было определить является ли число l, некоторой положительной степенью числа  k. Для этого можно делать одно из двух:
1) В 64-битном типе данных найти минимальную степень h числа k, такую что kh ≥ l. Если kh = l, то ответ YES, и число артиклей - h - 1, иначе NO.
2) Будем делить l на k, пока l делится на k и l ≠ 1. Если l = 1, то ответ - YES и число делений-1, иначе ответ NO.

Div 2. Задача B. PFAST Inc.
Задачу можно понимать следующим образом:
Дан граф, необходимо найти в нем клику наибольшего размера. Если взглянуть на ограничения n ≤ 16, то можно понять, что искомое подмножество вершин можно просто перебрать. Что мы и сделаем. Для удобства перебора можно воспользоваться бит. масками и просто перебрать до 216 чисел проверяя получаемый граф на то является ли он кликой. Единственное что остается - не забыть отсортировать имена при вводе.

Div 1. Задача A. Grammar Lessons
Данная задача скорее на аккуратную реализацию.
Половиной решения задачи является внимательное чтение условия. А именно - необходимо проверить набор слов который нам дается, на то  —  является ли он предложением в заданном нам языке. По условию корректным предложением является - 1 слово из нашей грамматики или же структура вида:
{ноль или несколько прилагательных} существительное {ноль или несколько глаголов}
Собственно авторское решение делало следующее:
Считаем все слова - если оно одно, то проверяем относится ли он к грамматике, иначе узнаем из первого слова - род. А дальше идем по всем словам проверяя, чтобы было согласование рода, наличие ровно 1 существительного, а также соблюдения порядка данного в условии.

Div 1. Задача B. Petr#
Данная задача имеет несколько решений. Начну с самого простого (правда которое с некоторой вероятностью можно взломать).
Первое решение. Посчитаем хеш-функцию от нашей строки. Тогда мы получаем возможность сравнивать подстроки за O(1). Далее пройдемся по всем позициям строки и найдем те в которых может начинаться begin, после чего для данной позиции найдем все подходящие позиции end которые подходят для данного begin, используя сравнение строк через хеши, после чего посчитаем число различных значений хеш-функции которые мы смогли получить (можно например используя массив для запоминания полученных хешей и сортировкой оного). Сложность - O(N2 Log N). Однако можно сделать более аккуратно, уменьшив вероятность коллизий. Для этого сначала найдем все возможные позиции начал, а после этого будем перебирать длину искомой подстроки и считать число уникальных хешей данной длины. Заметим что при этом мы все равно каждую подстроку переберем ровно 1 раз, однако коллизии будут возможно только между строками одной длинны, что менее вероятно, чем когда мы рассматриваем все строки.

Второе решение. В лоб найдем все возможные позиции начал и концов. После чего отобразим данную строку в число 0. После этого будем добавлять по 1 символу к имеющимся строкам и перенумеровывать строки данной длинны, т.е. уже строить для строк длины на 1 больше опять же отображения в целые неотрицательные числа. Заметим, что при этом у нас не будет никогда возникать более чем 2000 различных строк, поэтому мы их сможем спокойно перенумеровывать. Теперь учитывая, что мы знаем все концы строк, и различным строкам одной длины соответствуют разные числа, а одинаковым одинаковые, то мы без труда можем посчитать число различных подстрок указанной длины точно. Касательно сложности - O(N2 Log N), в силу того что всего у нас N итераций каждая из которых выполняется за время O(N Log N).

Третье решение. Используя суффиксный массив данную задачу можно решить за время O(N Log N). Построим суффиксный массив с LCP за O(N Log N). Далее найдем все вхождения строки end в нашу строку и запомним эти вхождения в отсортированном порядке в некотором массиве. Будем рассматривать последовательно наши суффиксы которые начинаются со строки begin (первое и последнее вхождение ищутся достаточно просто). Для начала рассмотрим первый суффикс который начинается с со строки begin. Для него любая строка закачивающаяся на end и такая что её длина больше чем max(|begin|, |end|) является искомой подстрокой, причем найти такую позицию строки end мы можем используя дихотомию по заранее посчитанному массиву вхождений концов (и тогда очевидным образом получаем сколько строк нам подходят). Рассмотрим следующий суффикс. Заметим что для следующего суффикса любая строка которая которая закачивается на расстоянии не больше чем LCP(i, i - 1) от начала строки (где i номер текущего суффикса), будет совпадать с некоторой подстрокой предыдущего суффикса, т.е. её мы посчитали. А любая строка заканчивающаяся после LCP(i, i - 1) (где i номер текущего суффикса) будет лексикографически больше любой рассмотренной ранее подстроки, а значит любое такое вхождение  —  новая подстрока. Используя дихотомию найдем в массиве концов - первый подходящий. Таким образом мы посчитали число различных подстрок в данных двух суффиксах. Продолжим делать таким образом пока не рассмотрим все суффиксы начинающиеся со строки begin. Таким образом мы получили ответ.
Теперь оценим сложность. На построение суффиксного массива мы потратили время O(N Log N). Построение массива концов - делается за O(N). Всего начал - не более чем N и при этом на каждой итерации мы тратим время O(Log N). Т.е. итоговая сложность O(N Log N).

Div. 1. Задача C. Double Happiness
В задаче необходимо было найти число простых чисел представимых в виде суммы двух квадратов натуральных чисел. Очевидно, что простые вида 4k + 3, не подходят, т.к. сумма двух квадратов не может быть сравнима с 3 по модулю 4. Что же касается простых вида 4k + 1, то можно доказать (ну а вообще это достаточно известный факт), что любое просто такого вида представимо в виде суммы двух квадратов натуральных чисел. Также необходимо не забыть про 2. Теперь касательно того как всё это можно сдать в систему. Очевидно, что совсем тупо писать решето Эратосфена не проходит по памяти, однако можно использовать блочное решето Эратосфена, которое работает за те же O(N Log Log N), однако использует в разы меньше памяти например . Помимо этого можно было использовать препросчет, и сократить объем работы до куска который влазит в память. Также участник Romka воспользовался идеей, что можно используя bit-mask уменьшить объем необходимой памяти для всего решета в 8 раз, что отлично влезло в ML. Так же неплохо при написании решета рассматривать, только нечетные числа.

Div. 1. Задача D. Museum
Для начала избавимся от того что у нас есть 2 человека, каждый из которых переходит в некоторую вершину. Для этого сделаем состоянием пару чисел (i, j) - которая обозначает, что Петя находится в комнате с номером i, а Вася в комнате с номером j. Тогда встрече в комнате i будет соответствовать состояние (i, i). Тогда исходя из этих данных несложно построить матрицу переходов - т.е. матрицу в которой для каждого состояния (i, j), известна вероятность перехода в состояние (x, y), где 1 ≤ i, j, x, y ≤ n. Так же понятно, что из состояния встречи мы переходим в это же состояние.
Теперь рассмотрим как решить данную задачу. Если бы нам было необходимо просто посчитать вероятность встречи в первой комнате, то можно было бы сделать следующим образом: построим систему линейных алгебраических уравнений:
, где a(i, j), (x, y) —  вероятность перехода из состояния (i,j) в состояние (x,y). При этом p(1, 1) = 1, а p(i, i) = 0 при i ≠ 1. При этом нас интересует p(a, b).
Данная СЛАУ легко решается методом Гаусса. Аналогичным образом можно решить для оставшихся вершин, однако при этом сложность выходит O(n7), что при данных ограничениях нас не очень устраивает. Однако можно заметить, что мы каждый раз решаем одну и ту же СЛАУ Ax = b (при условии, что у нас в матрице , единственное что меняется  —  вектор b), поэтому можно построить LU-разложение и пользуясь им получить сложность O(n6), однако можно не строить LU-разложения, просто решать матричное уравнение где b - матрица размерности n2 * n, а ответом является значение получившееся в строке соответствующей состоянию (a, b). При этом нетрудно видеть, что сложность получается опять же O(n6). Кроме этого можно решить задачу просто выразив все состояния через переменные соответствующие состояниям встреч.

Div. 1. Задача E. Sleeping
Введем функцию F(x) (где x - некоторый момент времени)  —  число моментов времени от 00..00:00..00 до x (т.е. x не переключается на следующий момент времени) когда сменится не менее чем k цифр. Тогда интересующим нас ответом будет являться F(h2: m2) - F(h1: m1), при этом мы учитываем что если h2: m2 < h1: m1, то F(h2: m2) будет на сутки больше.
Теперь научимся считать функцию F(x). Для начала посчитаем сколько наступит таких моментов без смены часа. Т.к. час у нас не меняется, то значит в минуте у нас должно поменяться не менее чем k цифр, но для того чтобы в числе поменялось не менее чем k цифр, необходимо, что наше число имело вид:
a..a99...9, где a - произвольные цифры, а на конце - k-1 девятка. Т.е. k цифр меняются каждое число кратное 10k - 1.
А значит в моменты в которые не меняется час у нас случилось таких событий , где hx и mx - число часов и минут в момент времени x, а [] - целая часть.
Теперь рассмотрим моменты когда меняется час. Если меняется час значит минут переходят из m - 1 в 0, и поэтому у нас уже отличается y цифр, где y - число не нулевых цифр числа m - 1. Значит нам надо аналогичным образом посчитать для часов, число моментов когда изменится не менее чем k - y цифр. k - y цифр меняется каждое число кратное 10max(0, k - y - 1), т.е. таких моментов  —  . Т.е. .

Если, что-то плохо описано или содержит опечатку/ошибку, отпишитесь в коментариях - исправлю.


Разбор задач Codeforces Beta Round 86 (Div. 1 Only)
Разбор задач Codeforces Beta Round 86 (Div. 2 Only)
  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Почему по задаче B hash+set не проходил? Не знаю какой у вас тест, у меня на ноуте все тесты проходили меньше 1.3 сек... Обидно =(
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Можно ли в задаче A (div2) пропихнуть на C++ решение вида:
long double result = log(L) / log(K);
если result -- целое число, то ответом будет "YES", result - 1; в противном случае "NO"?
p.s. не получается из-за неточности представления данных наверное.
p.p.s. где eps приписывать и поможет ли это? =)
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Можно получить как-то тест 24 по задаче B Div 1? А то никак не могу понять, как моё решение может найти несуществующее вхождение, а тест полностью не отображается
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Да, в этом и есть проблема. Большое спасибо. Пошел исправлять.

Upd: Прошло. Жаль, что не увидел во время контеста, что может быть такая ситуация
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

В С была какая-то фигня. Когда мой оптимизированный Эрастофен (битовый) стал наконец пролезать в запуске за 3.5с на макстесте- он тлился в претестах. Пришлось в 2 раза соптимизировать по памяти, оставив только нечетные числа
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

У меня по D решение такое же, просто для себя я объяснял его немного проще, на мой взгляд.

Пусть мы уже в новом графе хотим посчитать вероятность того, что мы стартуя из вершины i попадем в вершину j и там и останемся (считаем что из конечных вершин выхода нет). Тогда за один ход это можно сделать с вероятностью Aij. За два хода - с вероятностью A2ij и т.д. Получается, что нам нужно посчитать (A + A2 + A3 + ...)ij, а это просто сумма геометрической прогрессии с первым членом A и разностью A. Получаем, что матрица в скобках равна A * (E - A)-1.

На самом деле, нам подойдет и матрица (E - A)-1, если отдельно рассмотреть случай, когда начальные вершины в исходном графе совпадают.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
а разве отличие блочного решета от просто только в памяти? разницы во времени работы нет?
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
considering the problem  PFAST Inc. , 
is it possible to solve it greedy ??!
i mean ..
1.clear the person that doesn't get on well with the max number of people
if there still some one doesn't get on well with another
repeat 1
else
print the ans
__
is that okay?! 
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
What is this "block sieve" (mentioned as solution for problem Double Happiness)?
Anyone has a reference for an explanation of this algorithm?
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

I used a greedy approach to problem B, but it fails. I am still not sure why. Can anyone give a counter test.

1- Sort all volunteers by the number of people they don't get alone with.
2- Start with person with minimal conflicts, add it to team, and remove from sorted list all those who conflict with this guy.
3- Repeat.


15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Объясните мне, пожалуйста, задача B div 2, как используются битовые маски в данной задаче?)точнее причем здесь битовые маски?
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    См. следующий коммент (по ошибке не туда послал).
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Ок.
    Давайте для начала от имен перейдем к нумерованным вершинам в графе. Теперь, нам нужно найти такое подмножество вершин, чтобы оно являлось полным графом. Оценим, сколько у нас есть подмножеств. Их 2n - 1, так как пустое множество нас не устраивает. Закодируем каждое множество бинарной строкой a1......an, где ai = 0, если i-тая вершина не входит в множество, и ai = 1, если вершина входит в текущее множество. Тогда, каждую такую строку можно представить как двоичное представление некоторого числа X, причем так, что 0 ≤ X ≤ 2n - 1.
    Тогда, мы можем внешним циклом пройти по всем числам X, внутри проверим какие вершины входят в множество. И далее двойным циклом проверим, что текущий подграф является полным графом, ну и запомним текущее множество, если оно лучше оптимального перед этим шагом.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Так просто достаточно удобно перебрать все подмножества (хотя и обычный DFS тоже подходит).

Перенумеруем всех людей числами от 0 до n-1 (всего n людей). И будем рассматривать числа из n бит, при этом если i-ый бит равен 1, то берем соотсвествующего человека, иначе нет. Тогда если мы рассмотрим все числа от 0 до 2n - 1, то мы переберем все возможные подмножества из данного множества. А зная каких людей мы берем легко проверить, что все ли они не конфликтуют.

15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
ну вот к примеру, я имею n человек. создаю множества от 000000... до 11111... потом смотрю какое из этим множеств удовлетворяет тому, кого берем или нет. и это ответ? а как хранить эти множества вообще?))
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Повторю ещё раз (хотя по моему мой коммент выше более чем понятен). Каждое подмножество кодируется некоторым числом, причем каждое из них кодируется в ровно 1 число на отрезке [0, 2n - 1]. Далее проходим по всем числам на [0, 2n - 1], на основании числа получаем множество, его размер и подходит ли оно. Остается только запомнить то которое подошло (это просто число) и на основании его уже выводить ответ.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Есть такой код на задачу B(div-1): http://pastebin.com/Q5uQ41mS
Возможно, не без косяков, но на первом тесте он у меня стабильно выдает 1, а на codeforces - 0.
Никак не пойму в чем дело. Помогите разобраться.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Поправьте в Div 1 E в формулах mx-1 на mx и hx-1 на hx.
15 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится 0 Проголосовать: не нравится

Возникли проблемы с сортировкой в задаче Div 2 B. Ответ на 13 тест:
10
KgPQA
PIZRMOu
ToLcqN
XCKZ
XtueKFM
bnenhMxiK
eaQrds
jA
kyRNTE
mQIl
Решение сдавалось на C# и по собственным тестам он сортирует лексикографически, однако link выдал:
bnenhMxiK
eaQrds
fRNwNn
inOCWEZHxy
jA
kyRNTE
PIZRMOu
XtueKFM
yA
zlkOe
Написал сортировку этого набора на С++ с lexicographical_compare link и получил:
PIZRMOu
XtueKFM
bnenhMxiK
eaQrds
fRNwNn
inOCWEZHxy
jA
kyRNTE
yA
zlkOe

В чём моя ошибка?
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
I hope an solution for Petr# will be published soon.  I can only come up with an solution where I use a suffix array as a compressed trie.
15 лет назад, скрыть # |
 
Проголосовать: нравится +13 Проголосовать: не нравится
Is the editorial still under construction? I had been waiting for a completed one. 
Thanks.
»
6 лет назад, скрыть # |
Rev. 4  
Проголосовать: нравится 0 Проголосовать: не нравится

Suffix tree/array seems to be most efficient way to solve B.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Thanks. good editorial

»
4 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

In problem E, the formula of $$$F(x)$$$ should be

$$$ F(x)=h_x\left\lfloor\frac{m-1}{10^{k-1}}\right\rfloor+\left\lfloor\frac{m_x}{10^{k-1}}\right\rfloor+\left\lfloor\frac{h_x}{10^{\max(0,k-y-1)}}\right\rfloor $$$

Yes, there is some problem with border processing.

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

can anybody provide code for Div 1. Problem B. Petr# using editorial approach. i'm getting MLE :(