Автор andrewzta, 10 лет назад, По-русски

Задача А. Треугольники.

Идея: Андрей Станкевич.
Реализация: Анна Малова.
Разбор: Анна Малова.

В задаче требуется определить количество треугольников каждого типа, которые можно составить из четырех отрезков.

Переберем все возможные тройки отрезков. Из трех отрезков можно составить треугольник, если выполнено неравенство треугольника, то есть сумма любых двух сторон строго больше длины третьей стороны.

Рассмотрим отрезки a, b, c в порядке возрастания длины, тогда если выполнено равенство c2 = a2 + b2, то треугольник является прямоугольным, если c2 < a2 + b2 остроугольным, и если c2 > a2 + b2— тупоугольным

Задача B. Оригами.

Идея: Георгий Корнеев.
Реализация: Николай Ведерников.
Разбор: Николай Ведерников.

В задаче требуется проверить существует ли в прямоугольнике a на b подпрямоугольник площадью S, у которого стороны параллельны исходным.

Для этого переберём все такие x — делители числа S, и проверим, что xa и Sxb. Если существует хотя бы одна такая пара x и Sx, удолетворяющим ограничениям, то решение существует.

Время работы на один тестовый случай O(sqrt(S)).

Задача C. Митя и граф.

Идея: Жюри.
Реализация: Виталик Аксёнов.
Разбор: Виталик Аксёнов.

Первое наблюдение заключается в следующем: граф должен быть рёберным кактусом. Если он не получился таковым, то обязательно найдётся чётный цикл. Раз это кактус, то количество циклов равно m — (n — 1). А так как каждый цикл содержит в себе минимум 3 вершины, то 3·(m-(n — 1)) ≤ m. Отсюда получаем, что максимальное число рёбер равно 3·(n — 1) / 2.

При нечётных n, это мельница, то есть набор циклов длины 3, пересекающихся по 1 вершине, а при чётных n почти тоже самое, но еще одна висячая вершина соединена с любой другой ребром.

Задача D. Призы.

Идея: Виталик Аксёнов.
Реализация: Виталик Аксёнов.
Разбор: Виталик Аксёнов.

Мы знаем, что количества конфет, выданные участникам, должны убывать в зависимости от номера группы. Несложно убедиться, что любое удовлетворяющее разбиение конфет можно представить следующим способом:

  • В начале, в первой группе дети получают n конфет, во второй — n-1 конфет, ..., в последней — 1 конфету.
  • Далее мы можем прибавлять по одной конфете всем детям на префиксе групп. Это значит, что мы можем выбрать число p и увеличить ai на единицу для любого i ≤ p.

Так как мы выбрали изначальное распределение, то из общего числа конфет можно сразу вычесть n·a1+...+1·an. Несложно заметить, что операция распределения вычитает bp = a1+...+ap. Итого, нам надо проверить, можем ли мы представить d в виде какой-то суммы b1, ..., bn, а это стандартная задача о рюкзаке.

Время работы O(nd).

Задача Е. Криптостойкие ключи

Идея: Виталий Демьянюк.
Реализация: Виталий Демьянюк.
Разбор: Виталий Демьянюк.

Дано множество чисел a1, a2, ..., an. Его замкнули относительно операций НОД и НОК. Требуется выяснить, принадлежит ли заданное число v замкнутому множеству S.

Представим v в виде p1q1p2q2... pkqk, q i > 0 , где p1, p2, ..., pk — простые числа. Чтобы v принадлежало S необходимо чтобы для каждого i, 1 ≤  i ≤  k существовало j, 1 ≤  j ≤  n, такое что piqiaj и piqi+1aj . Этот факт следует из того, что мы можем любое число представить в виде НОК(НОД(...), НОД(...), ..., НОД(...)), так как min(a, max(b, c)) = max(min(a, b), min(a, c)) и max(a, min(b, c)) = min(max(a, b), max(a, c)). Положим ci равным наибольшему общему делителю чисел aj, таких что piqiaj . Если все ci делят v, то v принадлежит S. Оно может быть получено как наименьшее общее кратное всех ci. В противном случае v не принадлежит S(это следует из свойств операций НОД и НОК).

Время работы O(nk + sqrt(v) ), где k — количество простых делителей числа v.

  • Проголосовать: нравится
  • +25
  • Проголосовать: не нравится

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

Небольшая опечатка:

При нечётных n, это мельница, то есть набор циклов длины 3, пересекающихся по 1 вершине, а при нечётных n почти тоже самое, но еще одна висячая вершина соединена с любой другой ребром.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Спасибо, исправил.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

      В этой фразе остро не хватает "например". И дать задачу потом посчитать, сколько таких конфигураций.

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

Problem A. Triangles — альтернатива

Вы можете иметь простую функцию для расчета углов.

def angle (a, b, c):
    return math.degrees(math.acos((c**2 - b**2 - a**2)/(-2.0 * a * b)))

А потом проверить их с условиями.

if angleA != 0  and angleB != 0  and angleC != 0: 
	# не Существует
if angleA < 90  and angleB < 90  and angleC < 90:
	# остроугольный
if angleA == 90 or  angleB == 90 or  angleC == 90:
	# прямоугольный
if angleA > 90  or  angleB > 90  or  angleC > 90:
	# тупоугольный
  • »
    »
    10 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +7 Проголосовать: не нравится

    И потом встретить тест, в котором acos(eps) == PI/2 — eps

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +22 Проголосовать: не нравится

    Если задача легко решается в целых числах, то любое вещественночисленное решение автоматом становится абсолютно ненужным хламом, уж прости, товарищ.

  • »
    »
    10 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Мало того, что будут проблемы с точностью, как сказали выше. Если вывести такую формулу из теоремы косинусов: cos(angle) = (c^2-b^2-a^2)/(-2*a*b), а cos(angle)==0, если angle = 90, cos(angle)>0, если angle<90 и cos(angle) <0 если angle >90. Тогда можно просто рассчитывать косинус. Через cos = (c^2-b^2-a^2)/(-2*a*b), но тут можно заметить, что т.к. a и b всегда положительные, то просто можно считать r = (c^2-b^2-a^2), и сравнивать это с -cos, т.е. если r = 0 — треугольник прямоугольный, если r >0 — треугольник тупой, в остальных случаях острый. В итоге, получаем тоже решение что и в разборе.

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

В задаче D, уже перейдя ко второму уравнению, можно разделить его на один из коэффициентов (лучше всего на a1, так как он минимальный) и решать уже в остатках от него. Тогда получается решение со сложностью O(na12), что при заданных ограничениях должно быть быстрее, чем O(nd). Вот код — 6709851, это пока самое быстрое решение к этой задаче в "тренировках".

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

По поводу C объясните, пожалуйста, следующее:

Если два простых нечётных цикла пересекаются по как минимум одному ребру, то тогда существует чётный цикл. Это понятно. Но следует ли из этого существование простого чётного цикла?

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится

    Пусть у первого цикла длина l1, у второго l2, тогда сделаем цикл l1 + l2 — 2, где 2 это ребро по которому они пересекаются, его мы выкинем.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Это понятно. Что делать если пересечение не по одному ребру?

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится +1 Проголосовать: не нравится

        Эм, ну если пересечение по k ребрам, то длина нового цикла будет l1+l2-2*k, ведь ребро встречается в обоих циклах, что тоже является четным числом.

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится +1 Проголосовать: не нравится

          Мне кажется, что у такого способа (при нескольких рёбрах пересечения) есть небольшая проблема. Проблема в том, что может получиться сложный цикл (а не простой). На самом деле, может даже получиться несвязное объединение нечётных циклов.

          Пример: циклы ABCDE и ABFCD. Получаем треугольники BFC и AED (если я правильно понял метод).

  • »
    »
    10 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +1 Проголосовать: не нравится

    Назовём наши простые нечётные циклы L1 и L2.

    Так как они имеют общее ребро, то они пересекаются хотя бы по 2 вершинам. Эти вершины разбивают цикл L2 на цепи, внутри которых нет вершин L1, а концы являются вершинами из L1. Рассмотрим одну такую цепь (если вершин всего две, то цепей две, если три, то три (и так далее)). Пусть её концы — А и B. Есть 2 варианта:

    1) A и B не являются соседними в L1 или подцепи AB. Тогда оба пути, соединяющие A и B в L1, не пересекаются с AB (выбранная подцепь не может пересекать L1 нигде, так как все вершины из неё (кроме A и B) не лежат в L1, а ребро AB не присутствует либо в подцепи, либо в L1 по предположению) и имеют разную чётность. Тогда один из них можно приклеить к нашей цепи и получить простой чётный цикл.

    2) Они соседние в L1 и L2. Если это верно для любой выбранной подцепи (иначе проведём рассуждение из пункта 1), то любое ребро из L2 лежит в L1. Аналогично получаем, что любое ребро из L1 лежит в L2. Имеем L1 = L2, что не так.

    Надеюсь, нигде не ошибся.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Да, это похоже на правду. Спасибо большое!!!

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

Кто-нибудь знает, как просто объяснить факт: "Если все ci делят v, то v принадлежит S".

Буду очень признателен, если кто-нибудь объяснит, как придумать решение такой задачи. Я честно сидел выписывал формулы и не понимаю, как додуматься, что нужно взять ci именно такие, как описано. Может можно как-то интуитивно это понять.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +17 Проголосовать: не нравится

    Могу попробовать (сразу на оба вопроса). Каждому числу сопоставим разложение по простым, как в разборе: [q1, ..., qk]. Операция НОД  –  это MIN по каждой координате , а НОК  –  это MAX. Заметим здесь же, что никакие значения qi, отличные от тех, что получатся при разбивании исходных чисел, получить нельзя. Будем собирать наше требуемое v отдельно по каждой координате. Для координаты i нам нужно собрать из исходных aj какое-нибудь число, у которого в этой координате ровно qi, а в остальных как можно меньше. Потом сделаем НОК всех результатов для каждой координаты и получим то, что надо, если это вообще возможно.

    Собирать из исходных будем жадно: возьмём все те, у которых нужная координата не меньше, чем наша (это в разборе называется ), и сделаем им НОД, чтобы обрезать остальные координаты. "Если все ci делят v, то v принадлежит S" как раз означает, что остальные коордианты обрезались достаточно хорошо, т.е. не превысили соответствующих qj.

    Если ещё доказать, что если таким способом нельзя получить v, то нельзя и никаким другим, то получается решение. В разборе на это намекает предложение о возможности перестановки MIN и MAX.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Да, достаточно понятно. Хорошее объяснение, спасибо. :)