Во всех крупных IT-компаниях немалое внимание уделяется вопросам информационной безопасности, и Яндекс  — не исключение. Дима и Егор разрабатывают новый сервис YD (Yandex Dorogi) и в данный момент проводят аудит его безопасности. Для шифрования пользовательских данных в YD используется алгоритм шифрования с открытым ключом YS (Yandex Shifrovatel). Схема работы YS такова: для каждого сервиса генерируется закрытый ключ (), где  и  — натуральные числа. По закрытому ключу () генерируется открытый ключ (НОД(), НОК()), который доступен всем пользователям. Если злоумышленник сможет по открытому ключу получить закрытый ключ, то он получит доступ ко всем данным YD и принесет сервису непоправимый вред. Конечно же, Егор и Дима не могут этого допустить, поэтому они хотят сделать так, чтобы злоумышленнику пришлось перебрать очень много вариантов открытого ключа, прежде чем он сможет его угадать. Дима уже сгенерировал закрытый ключ для YD и получил на его основе открытый ключ (). Егору сразу же стало интересно, сколько вариантов закрытого ключа придется перебрать злоумышленнику для взлома YD в худшем случае, иными словами, сколько существует закрытых ключей () таких, что открытым ключом для них является (). К сожалению, у Егора есть много других задач, очень важных для запуска YD, поэтому он просит вас вычислить это количество за него.  В первой строке содержатся два целых числа  и  () — описание открытого ключа.  Выведите одно целое число — количество закрытых ключей, для которых данный ключ является открытым.  Входные данные  В первом примере существует два закрытых ключа, для которых () является открытым ключом: () и (). Во втором примере Дима ошибся, потому что ни один закрытый ключ не порождает открытый ключ (). В третьем примере подходящими закрытыми ключами являются (), (), (), (). НОД (наибольшим общим делителем) двух натуральных чисел  и  называется наибольшее число  такое, что  делится на  и  делится на . Например, НОД() равен , а НОД() равен . НОК (наименьшим общим кратным) двух натуральных чисел  и  называется наименьшее число  такое, что  делится на  и  делится на . Например, НОК() равен , а НОК() равен 20. Если  не делится на , то ответ, очевидно, равен нулю.  Иначе рассмотрим какую-то пару , , что , а . С каждой такой парой можно сопоставить два числа  и  такие, что , а .  Иными словами, задачу можно свести к задаче нахождения количества пар взаимно простых чисел ,  таких, что их  равен . Далее будем предполагать что , если это не так, то сводим исходную задачу к задаче , . Решение за . Зафиксируем , тогда ему в пару может подойти только , поскольку . Единственное, что надо проверить, это равенство , это можно сделать алгоритмом Евклида за . Под факторизацией подразумевается любой способ нахождения делителей. С учетом достаточно маленьких ограничений их можно найти просто проверкой всех целых чисел от  до , что имеет сложность . Известно, что количество делителей точно не превосходит , так что проверку, что , нужно выполнить не более  раз, что имеет сложность .  Получаем решение за . Решение за . Рассмотрим простое число , на которое делится . Если , то либо , либо  должно делится на , где  — максимальная степень, с которой  входит в . Чтобы выполнялось , одно из этих чисел не должно делиться на .  Иными словами, для каждого простого числа, на которое делится , мы выбираем, пойдет оно в  или в . Тогда ответ на задачу равен .

 Однажды программист Алексей из Яндекса взял отпуск и уехал отдыхать на море. В один из дней он пошел на пляж, причем пошел туда не один. Возможно, он пошел туда с мамой, возможно, с бабушкой, а, возможно, с другом или подругой. Важно, что пошел он туда не один. На пляже программист Алексей обнаружил, что осталось всего  () свободных лежаков. Но среди всего этого множества лежаков программисту Алексею нужно было всего лишь 2: для него самого и для того (или той), с кем он пришел. Так как программист Алексей очень любил порядок, то он хотел, чтобы лежаки были как можно более похожи друг на друга. Похожесть лежаков можно вычислить следующим образом:  Помогите программисту Алексею понять, какого минимального значения непохожести лежаков он может достичь, сравнив попарно все свободные лежаки.  В первой строке задано число  () – количество тестов. Каждый тест состоит из двух строк. В первой строке каждого теста задано число  () – количество лежаков. Во второй строке каждого теста заданы  чисел  (, ) – значения, которые были поставлены лежакам в соответствие по внешним признакам. Сумма  по всем тестам не превосходит .  Для каждого теста выведите по одной строке, в которой должно быть единственное число – минимальное значение непохожести.  Входные данные  В первом примере Алексей выберет лежаки со значениями 1 и 2. В первой части второго примера Алексей может взять только лежаки со значениями 2 и 4. Во второй части он выберет лежаки со значениями 4 и 6. Зададим все числа в их двоичном представлении, дополнив ведущими нулями так, чтобы их длины были одинаковы. Далее построим на этих значениях бор, где первое от корня ребро задается старшим разрядом: спускаясь вглубь дерева, вы переходите от старших разрядов к младшим.  Далее найдем все самые отдаленные от корня вершины, которые содержат ровно 2 числа. Каждой такой вершине поставим в соответствие число , равное XOR между числами, которое содержит эта вершина. Тогда ответ на задачу – это минимум всех чисел . Покажем, что это и правда ответ на задачу. Зададим расстояние от всех выбранных вершин до ближайших листьев числом  – оно также указывает на самый старший разряд, в котором числа отличаются (если , то числа равны). Тогда XOR между числами, принадлежащими разным сыновьям некоторой вершины, лежащей на расстоянии  от листьев, будет лежать в отрезке  (для  ответ , ибо числа полностью совпадают, для  ответ , ибо числа отличаются только в последнем разряде, для  ответ либо 2, либо 3 и т. д.). Если же ответ задачи достигается не на выбранных нами числах, то по построению получается, что они отличаются в каком-то разряде, старше . В таком случае числа будут отличаются хотя бы на . Получаем противоречие, ибо существует попарный XOR меньше. На самом деле, задачу можно решить без помощи бора, просто отсортировав все числа и взяв попарный XOR между соседними после сортировки числами. Ведь все числа, которые попадали в самые глубокие вершины, содержащие ровно 2 числа, являются также соседними числами после сортировки. Это действительно так, поскольку по построению бора ни одно другое число не может иметь значение из отрезка , где  и  – числа из некоторой выбранной нами вершины. Хранение данных в распределенном хранилище является крайне сложной задачей, однако инженеры Яндекса успешно с ней справляются. Один из кластеров хранилища состоит из  серверов, на которых хранятся данные, разбитые на  чанков. Для дефрагментации кластера и возможности отключения старых серверов чанки периодически приходится перемещать между серверами. Перемещение чанков по одному неэффективно, поэтому они перемещают группами. Запрос на перемещение описывается четырьмя числами  и обозначает заказ на перемещение всех чанков с номерами от  до  включительно с сервера с номером  на сервер с номером . После перемещения соотвествующие чанки с сервера с номером  стираются. Таким образом, каждый чанк находится всегда ровно на одном сервере. При построении распределенных систем очень важно избегать возможности конфликта изменений на кластере. Перед выполнением каждого из запросов необходимо убедиться, что все чанки, участвующие в запросе, находятся на ожидаемом сервере. Иными словами, перед выполнением запроса, описываемого параметрами , необходимо убедиться, что все чанки с номерами от  до  включительно расположены на сервере с номером . В случае, если это неверно, запрос на перемещение чанков отменяется и система переходит к обработке следующего запроса. Если же это верно, то запрос осуществляется и все чанки от  до  включительно перемещаются с сервера  на сервер . По заданному начальному состоянию кластера и списку запросов перемещения чанков определите, какие запросы будут выполнены.  В первой строке заданы три целых числа  и  () — количество чанков на кластере, количество серверов, на которых располагаются чанки, и количество запросов, соответственно. Во второй строке содержатся  чисел  (), -е из которых обозначает номер сервера, где изначально располагается чанк с номером . В следующих  строках содержатся описания запросов перемещения чанков в хронологическом порядке. Каждый запрос описывается четверкой чисел  () и обозначает заказ на перемещение чанков с номерами с  по  (включительно) с сервера  на сервер .  Выведите  строк. В строке с номером  выведите , если запрос с номером  будет выполнен, и , если нет.   Входные данные  Рассмотрим третий пример. Изначально расположение чанков на серверах описывается массивом . В первом запросе требуется переместить чанк с номером  с сервера  на сервер . Чанк с номером  находится на сервере , поэтому перемещение будет произведено. После выполнения запроса расположение чанков на серверах описывается массивом .  Во втором запросе требуется переместить чанки  и  с сервера  на сервер . Чанк  расположен не на сервере , а на сервере , поэтому операция не будет выполнена. Расположение чанков на серверах останется прежним. В третьем запросе требуется переместить чанк  с сервера  на сервер . Чанк  находится на сервере , поэтому перемещение будет произведено. После выполнения запроса расположение чанков на серверах будет описываться массивом . В четвертом запросе требуется переместить чанки  и  с сервера  на сервер . Так как чанк  расположен на сервере , а не на сервере , запрос не будет выполнен и расположение чанков останется прежним. В пятом запросе требуется переместить чанки  и  с сервера  на сервер , но чанк  расположен на сервере , поэтому запрос не будет выполнен и расположение чанков останется прежним. В шестом запросе требуется переместить чанк  с сервера  на сервер . Чанк с номером  находится на сервере , поэтому перемещение будет произведено и расположение чанков станет описываться массивом . Можно хранить для каждого сервера по одному декартову дереву, содержащему все находящиеся на нем чанки. Для этого при поступлении запроса нужно достать из декартова дерева, соответствующего вершине , все чанки от  до . Это можно сделать за 2 операции Split и одну операцию Merge, то есть за . Далее нужно проверить количество чанков, которые удалось достать из этого сервера. Если их в точности , то валидация пройдена и нужно вывести , если же нет, то ответ . Количество чанков можно проверить за .

Далее в зависимости от ответа вырезанные чанки нужно вернуть либо обратно на сервер , либо на сервер . Это делается с помощью одной операции Split и двух операций Merge, то есть за сложность . Итоговая сложность . Решение можно немного модифицировать и совершать меньше операций в случае ответа , но асимптотически сложность это не улучшит.

 Дан взвешенный неориентированный граф , содержащий  вершин и  ребер.  Разбейте вершины графа на два не пустых множества так, чтобы ребро минимального веса, соединяющее вершины из одного множества, имело максимально большой вес.  Гарантируется, что граф не содержит петель и его нельзя разбить так, чтобы такого ребра не существовало.  В первой строке задано число вершин  () и число ребер  () графа.  В следующих  строках заданы ребра в формате , ,  (, , ), где  и  задают начальную и конечную вершину ребра, а  — его вес.  В единственной строке выведите максимальный возможный вес ребра, которое имеет минимальный вес среди тех, что соединяют вершины, принадлежащие одному множеству.  Входные данные  Рассмотрим первый пример из условия. В нем возможно всего 3 различных разбиения, удовлетворяющих условию, рассмотрим каждое из них: 

 Получаем, что ответ на тест достигается при третьем варианте разбиения. Во втором тесте ответ достигается на разбиении . Легко убедиться, расписав все возможные разбиения, что не существует разбиения данного графа, на котором ответ был бы больше. Решить задачу можно с помощью бинарного поиска по ответу. Предположим, что ответ — . Тогда все ребра, вес которых меньше либо равен , должны соединять вершины из разных множеств, то есть двудольным является граф, построенный на ребрах с весом, меньшим либо равным . Покажем монотонность результата построения в зависимости от . Так, если для некоторого  можно построить граф, удовлетворяющий условию, то граф можно построить и для всех . Это следствие того, что для  можно взять такое же разбиение на множества, как и для , а в таком случае ребра между вершинами из одного множества будут иметь вес, больше либо равный . Если же для некоторого  нельзя построить граф, удовлетворяющий условию, то его нельзя построить и для , так как граф, построенный на ребрах весом меньше , не является двудольным (то есть существует ребро между вершинами из одного множества), а добавлением ребер нельзя восстановить двудольность графа. Теперь опишем проверку того, что граф удовлетворяет условию, то есть является двудольным. Для этого нужно запустить обход всех вершин (например, в глубину либо в ширину) для каждой компоненты связности. Во время обхода каждой вершине нужно поставить в соответствие  либо . Это делается так: 

 Сложность одной итерации бинарного поиска равна , а решение целиком имеет сложность . Разработчики Яндекс.Поиска постоянно работают над улучшением алгоритмов ранжирования. Один из алгоритмов, который хотят опробовать, таков. Поисковый алгоритм состоит из трех этапов: поиск по базе, отбор документов и фильтрация. Во время поиска по базе отбираются  документов-кандидатов для показа пользователю. Каждому документу сопоставляется целое число — релевантность, показывающее, насколько документ подходит пользователю. Чем выше релевантность, тем лучше документ подходит по данному запросу. Обратите внимание, что релевантность может быть даже отрицательной в случае, если документ не имеет никакого отношения к запросу.  Ранжирующий алгоритм хранит данные в закольцованном списке, таким образом, после документа с номером  () следующим в списке является документ с номером , а следующим после документа с номером  будет документ с номером . Во время отбора документов алгоритм выберет некоторый документ (назовем его начальным) и сколько-то следующих за начальным документов, которые будут переданы на фильтрацию. Во время фильтрации из списка документов, полученных при отборе, может быть удалено несколько документов, но не более . Кроме того, после фильтрации должен остаться хотя бы один документ. Оставшиеся после фильтрации документы показываются пользователю. Релевантностью выдачи назовем сумму релевантностей документов в ней. По релевантностям документов, полученных во время поиска, определите, какую наибольшую релевантность выдачи можно получить при оптимальной работе алгоритма.  В первой строке задано целое число  — количество тестовых случаев. Далее следует описание тестовых случаев. Описание каждого теста состоит из двух строк.  В первой строке задано два целых числа  и  (, ) — количество документов, полученных во время поиска, и максимальное количество документов, которые могут быть удалены после фильтрации соответственно.  Во второй строке содержатся  целых чисел  () — релевантности документов. Гарантируется что сумма  по всем тестовым случаям не превосходит .  Для каждого тестового случая выведите одно целое число — ответ на задачу.  Входные данные  В первом примере выгодно выбрать в качестве начального документ с релевантностью  и отправить на фильтрацию его и следующие 2 документа. На стадии фильтрации необходимо оставить все документы. Во втором примере выгодно выбрать в качестве начального любой документ с релевантностью , отправить на стадию фильтрации его и следующие за ним 2 документа. На стадии фильтрации необходимо удалить документ с релевантностью , таким образом, на выдачу попадут два документа с релевантностью . В пятом примере выгодно выбрать в качестве начального документ с номером  и отправить на стадию фильтрации его и следующие  документов. Таким образом, на стадию фильтрации попадут документы с релевантностями . На стадии фильтрации выгодно удалить документ с релевантностью , в результате чего на выдачу попадут документы с релевантностями  с суммарной релевантностью . В последнем примере релевантность выдачи получится отрицательной, так как пользователю необходимо показать хотя бы один документ. Если все релевантности документов отрицательны, то ответ — максимум по всем числам. Поскольку нам запрещено брать пустое множество, лучше обработать этот случай отдельно. Все последующие состояния динамики могут соответствовать пустому подотрезку с суммой , но это не улучшит ответ, поскольку мы всегда можем взять какой-то один неотрицательный элемент и это будет не хуже. Решим задачу, если нет цикличности массива.  Пусть  — максимальная сумма, которая может быть на каком-то подотрезке  ( тут не фиксировано и выбирается так, чтобы ответ был максимален), если из него удалили не более  элементов.  Пересчет: , что соответствует:  Такая динамика считается за , и ответом на задачу в этом случае является . Таким образом, мы учли все подотрезки массива, которые не проходят через стык первого и n-го элемента.  Теперь учтем оставшиеся отрезки. Пусть  — максимальная сумма, которая может быть на некотором подотрезке , если из него удалили ровно  элементов.  Пересчет: , что соответствует:   В отличие от первой динамики, нет необходимости начинать новый отрезок, поскольку левая граница фиксирована. Аналогично,  — максимальная сумма, которая может быть на некотором подотрезке , если из него удалили ровно  элементов.  Пересчет: , что соответствует:   Обе эти динамики можно посчитать за . Как теперь учесть все отрезки, проходящие через стык первого и n-го элемента? Переберем префикс , который войдет в ответ, а также количество элементов , которое мы удалили на этом префиксе. Самое оптимальное состояние — это . Теперь нужно соеденить это состояние с самым оптимальным суффиксом — если точнее, с . Этот максимум можно предпросчитать еще одной динамикой . Сложность такого предпросчета — , и после него можно находить оптимальный суффикс для каждой фиксированной пары  и  за . Получаем решение за  времени и памяти. Разработчик Алисы