Тема 19. Теория игр

19.04 Уменьшение количества камней

Вспоминай формулы по каждой теме
Решай новые задачи каждый день
Вдумчиво разбирай решения
ШКОЛКОВО.
Готовиться с нами - ЛЕГКО!
Подтемы раздела теория игр
Решаем задачи

Ошибка.
Попробуйте повторить позже

Задача 1#19950Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать в одной из куч два камня или уменьшить количество камней в куче в два раза (целочисленное деление). Чтобы делать ходы, у каждого игрока есть неограниченное количество камней. Количество камней не может быть отрицательно и игрок не может производить действие с кучей если она пуста. Игра завершается в тот момент, когда суммарное количество камней в кучах становится не более 12  . Победителем считается игрок, сделавший последний ход, т. е. первым получивший позицию, в которой в кучах будет 12  или меньше камней.

В начальный момент в первой куче было 25  камней, во второй куче — S  камней, 1 ≤ S ≤ 99  . Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника.

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

Показать ответ и решение
from functools import lru_cache


@lru_cache(None)
def f(a, b):
    if (a + b) <= 12:
        return 0
    moves = []
    if a - 2 >= 0:
        moves.append(f(a - 2, b))
    if b - 2 >= 0:
        moves.append(f(a, b - 2))
    if a > 0:
        moves.append(f(a // 2, b))
    if b > 0:
        moves.append(f(a, b // 2))
    petya_win = [i for i in moves if i <= 0]
    if petya_win:
        return -max(petya_win) + 1
    return -max(moves)


for i in range(1, 100):
    if i == 1:
        if f(25 - 2, i) == 1 or f(25 // 2, i) == 1 or f(25, i // 2) == 1:
            print(i)
            break
    else:
        if f(25 - 2, i) == 1 or f(25 // 2, i) == 1 or f(25, i // 2) == 1 or f(25, i - 2):
            print(i)
            break

Ответ: 1

Ошибка.
Попробуйте повторить позже

Задача 2#19953Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать в одной из куч три камня или уменьшить количество камней в куче в 5 раз (целочисленное деление). Чтобы делать ходы, у каждого игрока есть неограниченное количество камней. Количество камней не может быть отрицательно и игрок не может производить действие с кучей если она пуста. Игра завершается в тот момент, когда суммарное количество камней в кучах становится не более 75  . Победителем считается игрок, сделавший последний ход, т. е. первым получивший позицию, в которой в кучах будет 75  или меньше камней.

В начальный момент в первой куче было 100  камней, во второй куче — S  камней, 50 ≤ S ≤ 100  . Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника.

Известно, что Петя выиграл своим первым ходом. Назовите минимальное значение S  , при котором это возможно.

Показать ответ и решение
from functools import lru_cache


@lru_cache(None)
def f(a, b):
    if (a + b) <= 75:
        return 0
    moves = []
    if a - 3 >= 0:
        moves.append(f(a - 3, b))
    if b - 3 >= 0:
        moves.append(f(a, b - 3))
    if a > 0:
        moves.append(f(a // 5, b))
    if b > 0:
        moves.append(f(a, b // 5))
    petya_win = [i for i in moves if i <= 0]
    if petya_win:
        return -max(petya_win) + 1
    return -max(moves)


for i in range(50, 101):
    if f(100, i) == 1:
        print(i)

Ответ: 50

Ошибка.
Попробуйте повторить позже

Задача 3#23624Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать из одной из куч один камень или уменьшить количество камней в куче в два раза (если количество камней в куче нечётно, остаётся на 1  камень больше, чем убирается). Например, пусть в одной куче 6  , а в другой 9  камней; такую позицию мы будем обозначать (6,9)  . За один ход из позиции (6,9)  можно получить любую из четырёх позиций: (5,9)  , (3,9)  , (6,8)  , (6,5)  .

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

В начальный момент в первой куче было 20  камней, во второй куче — S  камней, S > 20.

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

Известно, что Петя выигрывает в первый ход. Укажите максимальное значение S,  когда такая ситуация возможна.

Показать ответ и решение

Решение 1

Петя может выиграть первым ходом, если S = 21,...,40  . Для выигрыша достаточно вдвое уменьшить количество камней во второй куче. При больших значениях S  за один ход нельзя получить 40  или менее камней в двух кучах.

 

Решение 2

from functools import lru_cache


@lru_cache(None)
def f(a, b):
    if a + b <= 40:
        return 0
    moves = []
    if a > 0:
        moves.append(f(a - 1, b))
        if a > 1:
            moves.append(f(a // 2 + (a % 2), b))
    if b > 0:
        moves.append(f(a, b - 1))
        if b > 1:
            moves.append(f(a, b // 2 + (b % 2)))
    petya_win = [i for i in moves if i <= 0]
    if petya_win:
        return -max(petya_win) + 1
    else:
        return -max(moves)


for i in range(20, 100):
    if f(20, i) == 1:
        print(i)

Ответ: 40

Ошибка.
Попробуйте повторить позже

Задача 4#23693Максимум баллов за задание: 1

Два игрока, Пинки и Вжик, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Пинки. За один ход игрок может убрать из одной из куч один камень или уменьшить количество камней в куче в два раза (если количество камней в куче нечётно, остаётся на 1  камень меньше, чем убирается). При любом из ходов кол-во камней в одной из куч должно измениться. Например, пусть в одной куче будет 6  камней, а в другой 9  камней; такую позицию мы будем обозначать (6,9)  . За один ход из позиции (6,9)  можно получить любую из четырёх позиций: (5,9),(6,8),(3,9),(6,4)  . Игра завершается в тот момент, когда суммарное количество камней в кучах становится не более 34  .

Победителем считается игрок, сделавший последний ход, то есть первым получивший позицию, в которой в кучах будет 34  или менее камней. В начальный момент в первой куче было 22  камня, во второй куче S  камней, S > 12

Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника. Описать стратегию игрока — значит описать, какой ход он должен сделать в любой ситуации, которая ему может встретиться при различной игре противника. В описание выигрышной стратегии не следует включать ходы играющего по этой стратегии игрока, не являющиеся для него безусловно выигрышными, т. е. не являющиеся выигрышными независимо от игры противника.

Найдите максимальное значение S  , при котором Вжик выигрывает своим первым ходом при любой игре Пинки.

Показать ответ и решение

Решение 1

Подпишем ячейки: A1  Start  , D1  P 1  . Поместим в ячейке A2  число 22  , а B2  наше значение S  . В ячейке C1  запишем формулу = A2 + B2  — там будет сумма камней во время старта

В ячейках E2 : F5  запишем все возможные пары куч, которые можно получить: в E2  поместим = A2 − 1  , в    F2  = B2  , в E3  поместим = (A2∕2)  (ЦЕЛОЕ возвращает как раз нужный нам результат деления), в F 3  = B2  , в E4  поместим = A2  , в F 2  = B2 − 1  , в E4  поместим = A2  , в F2  = (B2∕2)  . В ячейках столбца G  будем вести сумму куч (в G2  поместим = E2 + F 2  и растянем эту формулу на все пары куч).

В ячейке I2  запишем формулу = ((E2 : F 2)∕2)+ (E2 : F 2)  . Так мы получим сумму куч после самого аргессивного хода Вжика.

Условно окрасим в зеленый цвет ячейку I2  , если значение в ней меньше 35.

Постепенно перебирая значения ячейки B2  от 50 (например) вниз, заметим, что первый раз все ячейки результата выделяются зеленым при S = 26  . Значит, это максимальное значение, при котором выполняется условие.

Решение 2

from functools import lru_cache


@lru_cache(None)
def f(a, b):
    if a + b <= 34:
        return 0
    moves = []
    if a > 0:
        moves.append(f(a - 1, b))
        moves.append(f(a // 2, b))
    if b > 0:
        moves.append(f(a, b - 1))
        moves.append(f(a, b // 2))
    pinki_win = [i for i in moves if i <= 0]
    if pinki_win:
        return -max(pinki_win) + 1
    else:
        return -max(moves)


for i in range(12, 100):
    if f(22, i) == -1:
        print(i)

Ответ: 26

Ошибка.
Попробуйте повторить позже

Задача 5#23711Максимум баллов за задание: 1

Два игрока, Пупсень и Вупсень, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Пупсень. За один ход игрок может убрать из кучи один камень или убрать из кучи три камня. Например, имея кучу из 30 камней, за один ход можно получить кучу из 29 или 27 камней. Игра завершается в тот момент, когда количество камней в куче становится не более 11.

Победителем считается игрок, сделавший последний ход, то есть первым получивший позицию, в которой в куче будет 11 или менее камней. В начальный момент в куче было S камней, S > 11.

Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника. Описать стратегию игрока — значит описать, какой ход он должен сделать в любой ситуации, которая ему может встретиться при различной игре противника. В описание выигрышной стратегии не следует включать ходы играющего по этой стратегии игрока, не являющиеся для него безусловно выигрышными, т. е. не являющиеся выигрышными независимо от игры противника.

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

Показать ответ и решение
from functools import lru_cache


@lru_cache(None)
def f(a):
    if a <= 11:
        return 0
    moves = []
    if a > 0:
        moves.append(f(a - 1))
    if a > 2:
        moves.append(f(a - 3))
    pupsen_win = [i for i in moves if i <= 0]
    if pupsen_win:
        return -max(pupsen_win) + 1
    return -max(moves)


for i in range(12, 50):
    if f(i - 1) == 1 or f(i - 3) == 1:
        print(i)

Ответ: 17

Ошибка.
Попробуйте повторить позже

Задача 6#23802Максимум баллов за задание: 1

Два игрока, Наруто и Саске, играют в следующую игру. Перед игроками лежат три кучи кунаев. Игроки ходят по очереди, первый ход делает Наруто. За один ход игрок может убрать из одной из куч один кунай или уменьшить количество кунаев в куче в два раза (если количество кунаев в куче нечётно, остаётся на 1 кунай больше, чем убирается). При любом из ходов кол-во кунаев в одной из куч должно измениться. Например, пусть в первой куче будет 6 кунаев, во второй куче 7 кунаев, а в третьей 8 кунаев; такую позицию мы будем обозначать (6, 7, 8). За один ход из позиции (6, 7, 8) можно получить любую из шести позиций: (5, 7, 8), (6, 6, 8), (6, 7, 7), (3, 7, 8), (6, 4, 8), (6, 7, 4). Игра завершается в тот момент, когда суммарное количество кунаев в кучах становится не более 32.

Победителем считается игрок, сделавший последний ход, то есть первым получивший позицию, в которой в кучах будет 32 или менее кунаев. В начальный момент в первой и второй куче было 11 кунаев, в третьей куче S кунаев, S > 11  .

Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника. Описать стратегию игрока — значит описать, какой ход он должен сделать в любой ситуации, которая ему может встретиться при различной игре противника. В описание выигрышной стратегии не следует включать ходы играющего по этой стратегии игрока, не являющиеся для него безусловно выигрышными, т. е. не являющиеся выигрышными независимо от игры противника.

Известно, что Саске выиграл своим первым ходом после неудачного первого хода Наруто. Укажите максимальное значение S, когда такая ситуация возможна.

Показать ответ и решение
from functools import lru_cache


@lru_cache(None)
def f(first_heap, second_heap, third_heap, c=0):
    if first_heap + second_heap + third_heap <= 32:
        return 0
    if c > 4:
        return 123123
    moves = []
    if first_heap > 1:
        moves.append(f(first_heap - 1, second_heap, third_heap, c + 1))
        moves.append(f((first_heap + 1) // 2, second_heap, third_heap, c + 1))
    if second_heap > 1:
        moves.append(f(first_heap, second_heap - 1, third_heap, c + 1))
        moves.append(f(first_heap, (second_heap + 1) // 2, third_heap, c + 1))
    if third_heap > 1:
        moves.append(f(first_heap, second_heap, third_heap - 1, c + 1))
        moves.append(f(first_heap, second_heap, (third_heap + 1) // 2, c + 1))

    petya_win = [i for i in moves if i <= 0]
    if petya_win:
        return -max(petya_win) + 1
    else:
        return -max(moves)


for i in range(11, 100):
    if f(11 - 1, 11, i) == 1 or f((11 + 1) // 2, 11, i) == 1 or f(11, 11-1, i) == 1 or \
            f(11, (11 + 1) // 2, i) == 1 or f(11, 11, i - 1) == 1 or f(11, 11, (i + 1) // 2) == 1:
        print(i)

Ответ: 40

Ошибка.
Попробуйте повторить позже

Задача 7#26098Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать из одной из куч один камень или уменьшить количество камней в куче в два раза (если количество камней в куче нечётно, остаётся на 1 камень больше, чем убирается). Например, пусть в одной куче 6, а в другой 9 камней; такую позицию мы будем обозначать (6, 9). За один ход из позиции (6, 9) можно получить любую из четырёх позиций: (5, 9), (3, 9), (6, 8), (6, 5). Игра завершается в тот момент, когда суммарное количество камней в кучах становится не более 32. Победителем считается игрок, сделавший последний ход, то есть первым получивший позицию, в которой в кучах будет 32 или меньше камней. В начальный момент в первой куче было 10 камней, во второй куче – S  камней, S  > 22.

 

Найдите значение S  , при котором Ваня выигрывает своим первым ходом при любой игре Пети.

Показать ответ и решение
from functools import lru_cache


@lru_cache(None)
def f(a, b):
    if a + b <= 32:
        return 0
    moves = []
    if a > 0:
        moves.append(f(a - 1, b))
        if a > 1:
            moves.append(f(a // 2 + (a % 2), b))
    if b > 0:
        moves.append(f(a, b - 1))
        if b > 1:
            moves.append(f(a, b // 2 + (b % 2)))

    petya_win = [i for i in moves if i <= 0]
    if petya_win:
        return -max(petya_win) + 1
    else:
        return -max(moves)


for i in range(22, 100):
    if f(10, i) == -1:
        print(i)

Ответ: 45

Ошибка.
Попробуйте повторить позже

Задача 8#30379Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать из кучи один камень или убрать из кучи три камня. Например, имея кучу из 30  камней, за один ход можно получить кучу из 29  или 27  камней. Игра завершается в тот момент, когда количество камней в куче становится не более 7.

Победителем считается игрок, сделавший последний ход, то есть первым получивший позицию, в которой в куче будет 7  или менее камней. В начальный момент в куче было S  камней, S > 7.

Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника. Описать стратегию игрока — значит описать, какой ход он должен сделать в любой ситуации, которая ему может встретиться при различной игре противника. В описание выигрышной стратегии не следует включать ходы играющего по этой стратегии игрока, не являющиеся для него безусловно выигрышными, т. е. не являющиеся выигрышными независимо от игры противника.

Укажите максимальное значение S  , при котором Петя мог выиграть первым или вторым ходом, но совершил неверный ход и выиграл Ваня.

Показать ответ и решение

Решение руками

Неудачный ход – ход при котором игрок мог победить, но отдал победу противнику. Поэтому для начала найдем значения S  , при которых Петя мог победить за 1 или 2 хода.

Рассмотрим ситуацию, когда Петя сделал один ход. Чтобы получить число 7 есть всего 2 возможных хода: убрать из кучи один камень или убрать из кучи три камня. Для этих ходов подойдут значения S = 8  и S = 10  .

Теперь рассмотрим ситуацию, когда Петя сделал два хода. Так как мы знаем, что из S = 8  и S = 10  можно победить за 1 ход, то все ходы Вани должны приводить в эти значения, тогда перед ходом Вани S = 11  . И следовательно, чтобы Петя победил вторым ходом перед началом игры S = 12  и S = 14  .

Рассмотрим S = 14  . Первым ходом Петя делает неудачный ход – убирает 1 камень, S = 13  – из этой позиции нельзя победить за один ход, поэтому этот вариант не подходит.

Рассмотрим S = 12  . Первым ходом Петя делает неудачный ход – убирает 3 камня, S = 9  – из этой позиции можно победить за один ход, поэтому этот вариант подходит.

Идея решения:

Мы решаем задачу через моделирование игры с помощью рекурсивной функции. Каждая позиция в игре задаётся числом камней в куче. Если в куче 7  или меньше камней, то игра завершается, и функция возвращает 0  — это означает, что ходящий игрок проигрывает, так как не может больше ходить.

Далее, если в куче больше 7  камней, игрок может сделать один из двух ходов: убрать 1  камень или убрать  3  камня. Мы запускаем функцию рекурсивно для этих новых состояний. Если среди полученных значений есть такие, что противник оказывается в проигрышной позиции (отрицательные или нулевые значения), значит, текущая позиция является выигрышной для игрока, и мы возвращаем положительное число (номер хода, на котором он может выиграть). Если же все возможные ходы ведут к выигрышу противника, то текущая позиция является проигрышной, и возвращаем отрицательное число.

Далее мы перебираем все возможные начальные значения S  от 8  до 99  . Если значение функции для S  равно 1  или 2  , то это значит, что Петя имел выигрышную стратегию, позволяющую победить первым или вторым ходом. Чтобы учесть условие задачи (Петя совершает неверный ход и выигрывает Ваня), мы вручную проверяем оба варианта ходов Пети: S − 1  и S − 3  . Если хотя бы один из этих ходов приводит к позиции, из которой Ваня выигрывает первым ходом (значение функции равно 1  , таким образом мы проверяем, что из полученной позиции после хода Пети можно выиграть за один ход), то мы фиксируем, что именно при этом S  Петя мог выиграть, но ошибся, и в итоге выиграл Ваня. В конце выводим максимальное значение S  , удовлетворяющее условию задачи.

Решение программой

from functools import lru_cache

@lru_cache(None)
def game(heap):  # Функция игры
    if heap <= 7:  # Если камней в кучах стало меньше 7
        return 0  # Прекращаем игру
    moves = [game(heap - 1), game(heap - 3)]  # Генерация всех возможных ходов
    petya_win = [i for i in moves if i <= 0]
    if petya_win: # если в данной позиции есть выигрыш Пети
        return -max(petya_win) + 1
    else: # если в данной позиции выигрыш Вани
        return -max(moves)

for i in range(8, 100):
    if game(i) == 1 or game(i) == 2:  # Если Петя мог победить своим 1ым или 2м ходом

        # Для неудачного хода Пети нужно вручную сделать за него ходы от взятого s
        # и запустить функцию с изменнённым значением кучи, чтобы в хотя бы одном из ходов Петя ошибся.
        # Таким образом, Ваня станет первым ходившим игроком для функции,
        # и в итоге нужно будет получить значение 1 для победы Вани первым ходом после неудачного хода Пети.

        vanya_win = False  # Переменная-флаг, отвечающая за победу Вани (изначально Ваня не побеждает)
        if game(i - 1) == 1:  # Если при ходе -1 в итоге победит Ваня
            vanya_win = True
        if game(i - 3) == 1:  # Если при ходе -3 в итоге победит Ваня
            vanya_win = True

        if vanya_win:  # Если в итоге Ваня победил
            print(i)

Ответ: 12

Ошибка.
Попробуйте повторить позже

Задача 9#30382Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать из одной из куч один камень или уменьшить количество камней в куче в два раза (если количество камней в куче нечётно, остаётся на 1  камень меньше, чем убирается). При любом из ходов кол-во камней в одной из куч должно измениться. Например, пусть в одной куче будет 6  камней, а в другой    9  камней; такую позицию мы будем обозначать (6,9).  За один ход из позиции (6,9)  можно получить любую из четырёх позиций: (5,9),(6,8),(3,9),(6,4).  Игра завершается в тот момент, когда суммарное количество камней в кучах становится не более 12.

Победителем считается игрок, сделавший последний ход, то есть первым получивший позицию, в которой в кучах будет 12  или менее камней. В начальный момент в первой куче было 9  камня, во второй куче S  камней, S > 3

Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника. Описать стратегию игрока — значит описать, какой ход он должен сделать в любой ситуации, которая ему может встретиться при различной игре противника. В описание выигрышной стратегии не следует включать ходы играющего по этой стратегии игрока, не являющиеся для него безусловно выигрышными, т. е. не являющиеся выигрышными независимо от игры противника.

Найдите минимальное значение S,  при котором Ваня выигрывает своим первым ходом при любой игре Пети.

 

Показать ответ и решение

Решение руками

Очевидно, что при S ≤ 8  Петя выигрывает своим первым ходом (уменьшением кучи, в которой лежит 9  камней, в два раза). Значит при S = 9  Петя не сможет победить своим первым ходом, зато это сможет сделать Ваня. Ответ 9  .

 

Решение Excel

PIC

Создадим табличку, первый столбец которой назовём Старт, четвёртый Петя, а седьмой — Ваня.

В ячейку B4  запишем 9  , а в D4 запишем формулу =СУММ(B4:C4).

Так как Ване нужно победить первым ходом, то выгоднее всего ходить самым агрессивным ходом — делением на два. В ячейку H4  запишем формулу =ЦЕЛОЕ(МАКС(E4:F4)/2), в I4  — =МИН(E4:F4).

В ячейку J4 запишем формулу =СУММ(H4:I4), скопируем и вставим её в следующую клеточку.

В E4  запишем =B4-1, в F4− =C4, а в G4  — =СУММ(E4:F4).

Добавим условное форматирование. Выделим суммы, которые относятся к Пете и затем в разделе Главная выберем условное форматирование ⇒ Правила выделения ячеек ⇒ Меньше…, в открывшемся окошке записываем 13  и выбираем красный цвет. Выделим сумму, которая относится к старту, сделаем её зелёной по аналогии с суммой после хода Пети. То же самое сделаем с суммой, которая относится к Ване.

Скопируем полученную таблицу и вставим её три раза, каждый раз чуть ниже предыдущей. Заменим первые ходы Пети, чтобы не было повторов.

В начальную позицию запишем 9  и начнём подставлять значения в ячейку C4  , пока все суммы камней после хода Вани не станут зелёными.

 

Решение программой

from functools import lru_cache

@lru_cache(None)
def game(first_heap, second_heap):  # Функция игры
    if first_heap + second_heap <= 12:  # Если камней в кучах стало меньше 12
        return 0  # Прекращаем игру
    moves = [game(first_heap, second_heap // 2), game(first_heap // 2, second_heap),
             game(first_heap - 1, second_heap),game(first_heap, second_heap - 1)]  # Генерация всех возможных ходов
    petya_win = [i for i in moves if i <= 0]
    if petya_win: # если в данной позиции есть выигрыш Пети
        return -max(petya_win) + 1
    else: # если в данной позиции выигрыш Вани
        return -max(moves)

for i in range(4, 20):
    # если в данной позиции возможен выигрыш Вани первым ходом
    if game(9,i) == -1:
        print(i)
        break

Ответ: 9

Ошибка.
Попробуйте повторить позже

Задача 10#30397Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может либо убрать из кучи половину камней, если количество камней в куче делится на два, иначе убрать из кучи два камня, либо убрать из кучи две трети камней, если количество камней в куче делится на три, иначе убрать из кучи три камня. Например, пусть в куче будет 6  камней. Тогда за один ход можно получить кучу из 3  или 2  камней. Игра завершается в тот момент, когда количество камней в куче становится меньше или равно 2.

Победителем считается игрок, сделавший последний ход, то есть первым получивший позицию, в которой в куче будет 2  и менее камней. В начальный момент в куче было S  камней S > 2  .

Будем говорить, что игрок имеет выигрышную стратегию, если он может выиграть при любых ходах противника. Описать стратегию игрока — значит описать, какой ход он должен сделать в любой ситуации, которая ему может встретиться при различной игре противника. В описание выигрышной стратегии не следует включать ходы играющего по этой стратегии игрока, не являющиеся для него безусловно выигрышными, т. е. не являющиеся выигрышными независимо от игры противника.

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

Показать ответ и решение

Решение руками

Для начала найдем значения S  , при которых Петя мог победить за 1 ход. Чтобы получить число 2, есть всего 4 возможных хода: убрать половину камней, убрать два камня, убрать две трети камней, убрать три камня. Для всех этих ходов подойдут следующие значения S : 3,4,5,6.  Значит нужно рассмотреть только 4 значения S  и выбрать максимальное, чтобы Ваня мог победить при неудачном ходе Пети. Рассмотрим S = 6.  Первым ходом Петя делает неудачный ход делением на 2 (так как 6 делится на 2) в S = 3,  после чего Ваня например убирает из кучи две трети камней, создавая этим позицию S = 1,  в которой он побеждает.

Решение программой

from functools import lru_cache


@lru_cache(None)
def game(heap):  # Функция игры

    if heap <= 2:  # Если куча меньше или равна 2
        return 0  # Возвращаем стартовое значение 0

    # Список для возможных ходов,
    # которые нужно добавить в зависимости от условий
    steps = []
    # 1 Условие
    if heap % 2 == 0:
        steps += [game(heap // 2)]  # Убираем половину
    else:
        steps += [game(heap - 2)]  # Убираем 2 камня
    # 2 Условие
    if heap % 3 == 0:
        steps += [game(heap // 3)]  # Убрать две трети равносильно оставить одну треть
    else:
        steps += [game(heap - 3)]  # Убираем 3 камня

    petya_win = [x for x in steps if x <= 0]  # Выигрышные позиции для пети

    if petya_win:  # Если такие значения есть
        return -max(petya_win) + 1
    return -max(steps)


for s in range(3, 100):
    if game(s) == 1:  # Если Петя мог победить своим 1ым ходом

        # Для неудачного хода Пети нужно вручную сделать за него ходы от взятого s
        # и запустить функцию с изменнённым значением кучи, чтобы в хотя бы одном из ходов Петя ошибся.
        # Таким образом, Ваня станет первым ходившим игроком для функции,
        # и в итоге нужно будет получить значение 1 для победы Вани первым ходом после неудачного хода Пети.

                                                                                                     
                                                                                                     
        vanya_win = False  # Переменная-флаг, отвечающая за победу Вани (изначально Ваня не побеждает)
        if s % 2 == 0:
            if game(s // 2) == 1:  # Если при ходе //2 в итоге победит Ваня
                vanya_win = True
        else:
            if game(s - 2) == 1:  # Если при ходе -2 в итоге победит Ваня
                vanya_win = True
        if s % 3 == 0:
            if game(s // 3) == 1:  # Если при ходе //3 в итоге победит Ваня
                vanya_win = True
        else:
            if game(s - 3) == 1:  # Если при ходе -3 в итоге победит Ваня
                vanya_win = True

        if vanya_win:  # Если в итоге Ваня победил
            print(s)

Ответ: 6

Ошибка.
Попробуйте повторить позже

Задача 11#139229Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может: убрать из кучи три камня, или убрать из кучи семь камней, или уменьшить количество камней в куче в четыре раза (количество камней, полученное при делении, округляется до меньшего). Например, из кучи в 21 камень за один ход можно получить кучу из 18, 14 или 5 камней.

Игра завершается, когда количество камней в куче становится не более 21.

Победителем считается игрок, сделавший последний ход, то есть первым получивший кучу, в которой будет 21 или меньше камней.

В начальный момент в куче было S камней, S ≥ 22  .

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

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

Показать ответ и решение

Решение руками
Для начала определим значения, из которых Петя выигрывает за один ход. Максимально уменьшить количество камней можно, поделив на 4  , поэтому максимальное значение для победы за один ход равно 21 ⋅4 = 84  . Если учитывать округление вниз, числа до 87  также приводят к победе за один ход. Таким образом, при 22 ≤ S ≤ 87  игрок побеждает за один ход. Чтобы Ваня мог выиграть при любом ходе Пети, Петя должен передать Ване выигрышную позицию, то есть все свои ходы должны привести к диапазону 22...87  . Это возможно при S = 88,89,90  . В ответ записываем минимальное значение S  , то есть 88  .

Решение программой
Для решения на Python используем рекурсию с проверкой всех возможных ходов, чтобы определить, чья это выигрышная позиция. Функция возвращает 0  , если игра уже завершена (камней ≤ 21  ), положительное число – если при оптимальной игре побеждает текущий игрок, и отрицательное – если побеждает соперник. Так как первый ход делает Петя, цикл запускается от его лица: если значение функции положительное, выигрыш принадлежит Пете, а если отрицательное – Ване. При переборе возможных S  программа находит три числа S, в ответ записываем минимальное

from functools import lru_cache


@lru_cache(None) # Кэширует предыдущие значения функции, что позволяет ускорить работу программы
def game(first_heap):  # Функция игры
    if first_heap <= 21:  # Если камней в куче стало не более 21
        return 0  # Прекращаем игру
    moves = [game(first_heap - 3), game(first_heap - 7), game(first_heap // 4)]  # Прописываем возможные ходы в партии
    win = [i for i in moves if i <= 0]
    if win:  # Проверяем, есть ли выигрыш в данной позиции
        return -max(win) + 1
    else:  # Если в данной позиции выигрыш соперника
        return -max(moves)


for i in range(22, 100):
    if game(i) == -1:  # Если в данной позиции возможен выигрыш Вани первым ходом
        print(i)

Ответ: 88

Ошибка.
Попробуйте повторить позже

Задача 12#139231Максимум баллов за задание: 1

Для игры, описанной в задании 19, найдите два таких минимальных значения S  , при которых у Пети есть выигрышная стратегия, причём одновременно выполняются два условия:

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

Найденные значения запишите в ответе в порядке возрастания без пробелов или других разделителей.

Показать ответ и решение

Решение руками
Из предыдущего задания известно, что позиции, из которых Ваня гарантированно выигрывает своим первым ходом, равны S = 88,89,90  . Чтобы Петя мог выиграть своим вторым ходом независимо от действий Вани, хотя бы один его ход должен переводить игру в эти позиции, так что Ваня гарантированно проиграет за один ход. Рассмотрим все возможные ходы Пети: уменьшение на 3  , уменьшение на 7  и деление на 4  с округлением вниз. Тогда получаем:

S − 3 ∈ {88,89,90} ⇒ S = 91,92,93,

S − 7 ∈ {88,89,90} ⇒ S = 95,96,97,

⌊S∕4⌋ ∈ {88,89,90} ⇒ S = 352,353,354,355,356,357,358,359,360,361,362,363.

Следовательно, минимальные значения S  , при которых Петя выигрывает своим вторым ходом, это 91  и 92  .

Решение программой
Этот код очень похож на реализацию из задачи 19: он также использует рекурсию для проверки всех возможных ходов (− 3  , − 7  , ÷ 4  с округлением вниз) и определяет выигрышные позиции. Отличие лишь в том, что здесь мы ищем значения S  , при которых Петя выигрывает своим вторым ходом, проверяя game(S) == 2.

from functools import lru_cache


@lru_cache(None) # Кэширует данные, ускоряя работу программы
def game(first_heap):  # Функция игры
    if first_heap <= 21:  # Если камней в куче стало не более 21
        return 0  # Прекращаем игру
    moves = [game(first_heap - 3), game(first_heap - 7), game(first_heap // 4)]  # Прописываем возможные ходы в партии
    win = [i for i in moves if i <= 0]
    if win:  # Проверяем, есть ли выигрыш в данной позиции
        return -max(win) + 1
    else:  # Если в данной позиции выигрыш соперника
        return -max(moves)


for i in range(22, 1000):
    if game(i) == 2:  # Если в данной позиции возможен выигрыш Пети за два хода
        print(i)

Ответ: 9192

Ошибка.
Попробуйте повторить позже

Задача 13#139234Максимум баллов за задание: 1

Для игры, описанной в задании 19, найдите минимальное значение S  , при котором одновременно выполняются два условия:

– у Вани есть выигрышная стратегия, позволяющая ему выиграть первым или вторым ходом при любой игре Пети;

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

Показать ответ и решение

Решение руками
Из предыдущих заданий известно, что Петя гарантированно побеждает своим вторым ходом из позиций

91...93, 95...97, 352...363,

а своим первым ходом – из позиций на отрезке [22;87]  . Нам нужно найти минимальное S > 87  , при котором все ходы Пети переводят игру в эти выигрышные позиции, чтобы Ваня гарантированно выигрывал первым или вторым ходом.

Проверим подряд кандидаты, начиная с S = 88  .

  • S = 88  : после ходов Пети получаем 85, 81, 22  – все в [22;87]  , значит Ваня выигрывает сразу первым ходом при любых ходах Пети, поэтому 88  не подходит (нужна ситуация, когда Ваня не гарантированно выигрывает первым ходом).
  • S = 89  : после ходов Пети получаем 86, 82, 22  – опять все в [22;87]  , поэтому не подходит.
  • S = 90  : после ходов Пети получаем 87, 83, 22  – опять все в [22;87]  , не подходит.
  • S = 91  : после ходов Пети получаем 88, 84, 22  . Здесь 88 ∕∈ [22;87]  и 88∈∕{91...93,95...97,...} , значит для хода Пети в 88  Ваня не получает гарантированного выигрыша за 1 или 2 хода, поэтому 91  не подходит.
  • S = 92,93  аналогично дают одно из образовавшихся значений вне множества выигрышных позиций, поэтому тоже не подходят.
  • S = 94  : после ходов Пети получаем

    94 − 3 = 91 ∈ {91 ...93},  94− 7 = 87 ∈ [22;87],   ⌊94∕4⌋ = 23 ∈ [22;87].

    Все три результата принадлежат либо множеству позиций «выигрыш за 1 ход» ([22;87]  ), либо множеству позиций «выигрыш за 2 хода» (91...93, 95...97, 352...363  ). Значит при любом ходе Пети Ваня имеет выигрышную стратегию, позволяющую ему выиграть первым или вторым ходом, и при этом не во всех ветках у Вани есть мгновенная победа за 1 ход (поскольку для хода Пети, давшего 91  , Ваня выигрывает вторым ходом).

Следовательно, минимальное значение S  , удовлетворяющее требованиям, равно 94

Решение программой
Этот код почти идентичен реализации из задачи 19, а единственное отличие заключается в условии проверки в цикле: здесь проверяется game(S) == -2, что соответствует поиску начальных значений S  , из которых Ваня выигрывает первым или вторым ходом.

from functools import lru_cache


@lru_cache(None) # Кэширует данные, ускоряя работу программы
def game(first_heap):  # Функция игры
    if first_heap <= 21:  # Если камней в куче стало не более 21
        return 0  # Прекращаем игру
    moves = [game(first_heap - 3), game(first_heap - 7), game(first_heap // 4)]  # Прописываем возможные ходы в партии
    win = [i for i in moves if i <= 0]
    if win:  # Проверяем, есть ли выигрыш в данной позиции
        return -max(win) + 1
    else:  # Если в данной позиции выигрыш соперника
        return -max(moves)


for i in range(22, 1000):
    if game(i) == -2:  # Если в данной позиции возможен выигрыш Вани за один или два хода
        print(i)

Ответ: 94

Ошибка.
Попробуйте повторить позже

Задача 14#140192Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может выполнить любое из следующих трёх действий:

1) убрать из кучи один камень;

2) если количество камней в куче кратно трём, уменьшить его в три раза, в противном случае убрать из кучи два камня;

3) если количество камней в куче кратно пяти, уменьшить его в пять раз, в противном случае убрать из кучи три камня.

Например, если в куче 12 камней, то за один ход можно получить 11, 4 или 9 камней.

Игра завершается, когда количество камней в куче становится не более 19.

Победителем считается игрок, сделавший последний ход, то есть первым получивший кучу, в которой будет 19 или меньше камней.

В начале игры в куче было S камней, S > 19.

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

Показать ответ и решение

Решение руками

Поймём, что значение 20  - победа Пети, ведь он сразу может вычесть 1  .

Значение 21  не делится на 5  , значит можно вычесть 3  и получить победу Пети.

Значение 22  не делится на 5  , значит можно вычесть 3  и получить победу Пети.

Значение 23  не делится на 5  , значит можно вычесть 3  и получить 20  , из которого сможет выиграть Ваня. Если вычесть 1  , то из 22  можно получить 19  аналогично прошлым шагам, Ваня победит. Значение 23  не делится на    3  , вычитаем 2  , а из 21  Ваня вновь сможет одержать победу. При всех трёх значениях Петя никак не может выиграть.

Ответ: 23

Решение программой:
Для решения на Python используем рекурсию с проверкой всех возможных ходов (− 1  , делить на 3  , делить на  5  ), чтобы определить, чья это выигрышная позиция.
Функция возвращает 0  , если игра уже завершена (камней ≤ 19  ), положительное число — если при оптимальной игре побеждает текущий игрок, и отрицательное – если побеждает соперник.
Так как первый ход делает Петя, цикл запускается от его лица: если значение функции положительное, выигрывает Петя, а если отрицательное – Ваня. Если функция вернёт − 1  - значит Петя гарантированно проиграл первым ходом, а Ваня выиграл. При переборе возможных начальных значений программа выводит 23  .

# lru_cache позволит сэкономить ресурсы компьютера. Функция будет сохранять прошлые значения функций, а значит не придётся считать из заново.
from functools import lru_cache
@lru_cache(None)
def game(first_heap): # Функция игры
    if first_heap <= 19: # Если камней в куче стало меньше или равно 19
        return 0 # Прекращаем игру
    if first_heap % 3 == 0: # Занесём в b значение функции исходя из кратности числа (по условию)
        b = game(first_heap // 3)
    else:
        b = game(first_heap - 2)
    if first_heap % 5 == 0: # Занесём в с значение функции исходя из кратности числа (по условию)
        c = game(first_heap // 5)
    else:
        c = game(first_heap - 3)
    moves = [game(first_heap - 1), b, c] # Прописываем ходы возможные в партии
    petya_win = [i for i in moves if i <= 0]
    if petya_win: # Проверяем есть ли выигрыш Пети в данной позиции
        return -max(petya_win) + 1 # От лица Пети будет выигрыш (положительное число, прибавляем 1, поскольку это будет уже следующий ход)
    else: # Если в данной позиции выигрыш Вани
        return -max(moves) # От лица Пети будет проигрыш (отрицательное число)

for i in range(20, 100): # Переберём возможные значения (единицу не берём из-за возведения в квадрат, ведь программа будет бесконечной)
    if game(i) == -1: # Если в данной позиции возможен выигрыш Вани вторым ходом
        print(i) # Выведем нужное значение

Ответ: 23

Ошибка.
Попробуйте повторить позже

Задача 15#140201Максимум баллов за задание: 1

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может выполнить любое из следующих трёх действий:

1) убрать из кучи один камень;

2) если количество камней в куче кратно трём, уменьшить его в три раза, в противном случае убрать из кучи два камня;

3) если количество камней в куче кратно пяти, уменьшить его в пять раз, в противном случае убрать из кучи три камня.

Например, если в куче 12 камней, то за один ход можно получить 11, 4 или 9 камней.

Игра завершается, когда количество камней в куче становится не более 17.

Победителем считается игрок, сделавший последний ход, то есть первым получивший кучу, в которой будет 17 или меньше камней.

В начале игры в куче было S камней, S > 17.

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

Показать ответ и решение

Решение руками

Поймём, что значение 18  - победа Пети, ведь он сразу может вычесть 1  .

Значение 19  не делится на 5  , значит можно вычесть 3  и получить победу Пети.

Значение 20  делится на 5  , значит можно поделить и получить победу Пети.

Значение 21  делится на 3  , значит можно поделить и получить победу Пети.

Значение 22  не делится на 5  , значит можно вычесть 3  и получить 19  , из которого сможет выиграть Ваня (− 3  ). Если вычесть 1  , то из 21  можно получить 7  , Ваня победит. Значение 22  не делится на 3  , вычитаем  2  , а из 20  Ваня вновь сможет одержать победу (− 3  ). При всех трёх значениях Петя никак не может выиграть.

Ответ: 22

Решение программой:
Для решения на Python используем рекурсию с проверкой всех возможных ходов (− 1  , делить на 3  , делить на  5  ), чтобы определить, чья это выигрышная позиция.
Функция возвращает 0  , если игра уже завершена (камней ≤ 17  ), положительное число — если при оптимальной игре побеждает текущий игрок, и отрицательное – если побеждает соперник.
Так как первый ход делает Петя, цикл запускается от его лица: если значение функции положительное, выигрывает Петя, а если отрицательное – Ваня. Если функция вернёт − 1  - значит Петя гарантированно проиграл первым ходом, а Ваня выиграл. При переборе возможных начальных значений программа выводит 22  .

# lru_cache позволит сэкономить ресурсы компьютера. Функция будет сохранять прошлые значения функций, а значит не придётся считать из заново.
from functools import lru_cache
@lru_cache(None)
def game(first_heap): # Функция игры
    if first_heap <= 17: # Если камней в куче стало меньше или равно 17
        return 0 # Прекращаем игру
    if first_heap % 3 == 0: # Занесём в b значение функции исходя из кратности числа (по условию)
        b = game(first_heap // 3)
    else:
        b = game(first_heap - 2)
    if first_heap % 5 == 0: # Занесём в с значение функции исходя из кратности числа (по условию)
        c = game(first_heap // 5)
    else:
        c = game(first_heap - 3)
    moves = [game(first_heap - 1), b, c] # Прописываем ходы возможные в партии
    petya_win = [i for i in moves if i <= 0]
    if petya_win: # Проверяем есть ли выигрыш Пети в данной позиции
        return -max(petya_win) + 1 # От лица Пети будет выигрыш (положительное число, прибавляем 1, поскольку это будет уже следующий ход)
    else: # Если в данной позиции выигрыш Вани
        return -max(moves) # От лица Пети будет проигрыш (отрицательное число)

for i in range(20, 100): # Переберём возможные значения (единицу не берём из-за возведения в квадрат, ведь программа будет бесконечной)
    if game(i) == -1: # Если в данной позиции возможен выигрыш Вани вторым ходом
        print(i) # Выведем нужное значение

Ответ: 22

Ошибка.
Попробуйте повторить позже

Задача 16#140793Максимум баллов за задание: 1

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

– убрать из кучи один камень;

– если количество камней в куче чётно, убрать половину имеющегося количества;

– если количество камней в куче кратно трём, убрать треть имеющегося количества.

Например, если в куче 4 камня, то за один ход можно получить 2 или 3 камня, а если в куче 6 камней, то за один ход можно получить 3, 4 или 5 камней. Игра завершается, когда количество камней в куче становится меньше 10. Победителем считается игрок, сделавший последний ход, то есть первым получивший кучу, в которой будет меньше 10 камней. В начале игры в куче было S камней, S ≥ 10  . Укажите максимальное значение S, при котором Петя не может выиграть первым ходом, но при любом первом ходе Пети Ваня может выиграть своим первым ходом.

Показать ответ и решение

Решение руками:

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

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

Тогда сделаем действия в обратном порядке. Больше всего камней отнимает деление на два, будем делать его от максимального числа для выигрыша - 9  .

9⋅2 = 18  . Значит из 18 Ваня смог бы моментально выиграть. Остаётся добавить единицу, ведь у Пети просто не будет выбора.

Число 19  определённо нам подходит. Петя уменьшит его на единицу, а Ваня поделит на 2  , выиграв первым ходом.

Больше 19  рассматривать смысла нет, ведь мы провернули все действия от максимального победного числа в обратном порядке. К тому же увеличили его в 2  раза, что является максимально возможным увеличением за раз.

Ответ: 19

Решение программой:
Для решения на Python используем рекурсию с проверкой всех возможных ходов (− 1  , делить на 2  , делить на  3  ), чтобы определить, чья это выигрышная позиция.
Функция возвращает 0  , если игра уже завершена (камней ≤ 9  ), положительное число — если при оптимальной игре побеждает текущий игрок, и отрицательное – если побеждает соперник.
Так как первый ход делает Петя, цикл запускается от его лица: если значение функции положительное, выигрывает Петя, а если отрицательное – Ваня. Если функция вернёт − 1  - значит Ваня гарантированно выиграл первым ходом. При переборе возможных начальных значений программа выводит максимум 19  .

# lru_cache позволит сэкономить ресурсы компьютера. Функция будет сохранять прошлые значения функций, а значит не придётся считать из заново.
from functools import lru_cache
@lru_cache(None)
def game(first_heap): # Функция игры
    b = 100000000000000000000000000  # В b и c будут записаны результаты определённых ходов, если они возможны
    c = 100000000000000000000000000
    if first_heap <= 9: # Если камней в куче стало меньше или равно 9
        return 0 # Прекращаем игру
    if first_heap % 3 == 0: # Занесём в b значение функции исходя из кратности числа (по условию)
        b = game(first_heap * 2 // 3) # Уберём треть числа
    if first_heap % 2 == 0: # Занесём в с значение функции исходя из кратности числа (по условию)
        c = game(first_heap // 2)
    moves = [game(first_heap - 1)] # Прописываем ходы возможные в партии
    if b != 100000000000000000000000000:
        moves.append(b)
    if c != 100000000000000000000000000:
        moves.append(c)
    petya_win = [i for i in moves if i <= 0]
    if petya_win: # Проверяем есть ли выигрыш Пети в данной позиции
        return -max(petya_win) + 1 # От лица Пети будет выигрыш (положительное число, прибавляем 1, поскольку это будет уже следующий ход)
    else: # Если в данной позиции выигрыш Вани
        return -max(moves) # От лица Пети будет проигрыш (отрицательное число)

for i in range(10, 1000): # Переберём возможные значения (единицу не берём из-за возведения в квадрат, ведь программа будет бесконечной)
    if game(i) == -1: # Если в данной позиции возможен выигрыш Вани первым ходом
        print(i) # Выведем нужное значение

Ответ: 19

Ошибка.
Попробуйте повторить позже

Задача 17#140825Максимум баллов за задание: 1

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

– убрать из кучи один камень;

– если количество камней в куче чётно, убрать половину имеющегося количества;

– если количество камней в куче кратно трём, убрать треть имеющегося количества.

Например, если в куче 4 камня, то за один ход можно получить 2 или 3 камня, а если в куче 6 камней, то за один ход можно получить 3, 4 или 5 камней. Игра завершается, когда количество камней в куче становится меньше 12. Победителем считается игрок, сделавший последний ход, то есть первым получивший кучу, в которой будет меньше 12 камней. В начале игры в куче было S камней, S ≥ 12  . Укажите максимальное значение S, при котором Петя не может выиграть первым ходом, но при любом первом ходе Пети Ваня может выиграть своим первым ходом.

Показать ответ и решение

Решение руками:

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

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

Тогда сделаем действия в обратном порядке. Больше всего камней отнимает деление на два, будем делать его от максимального числа для выигрыша - 11  .

11⋅2 = 22  . Значит из 22 Ваня смог бы моментально выиграть. Остаётся добавить единицу, ведь у Пети просто не будет выбора.

Число 23  определённо нам подходит. Петя уменьшит его на единицу, а Ваня поделит на 2  , выиграв первым ходом.

Больше 23  рассматривать смысла нет, ведь мы провернули все действия от максимального победного числа в обратном порядке. К тому же увеличили его в 2  раза, что является максимально возможным увеличением за раз.

Ответ: 23

Решение программой:
Для решения на Python используем рекурсию с проверкой всех возможных ходов (− 1  , делить на 2  , делить на  3  ), чтобы определить, чья это выигрышная позиция.
Функция возвращает 0  , если игра уже завершена (камней ≤ 12  ), положительное число — если при оптимальной игре побеждает текущий игрок, и отрицательное – если побеждает соперник.
Так как первый ход делает Петя, цикл запускается от его лица: если значение функции положительное, выигрывает Петя, а если отрицательное – Ваня. Если функция вернёт − 1  - значит Ваня гарантированно выиграл первым ходом. При переборе возможных начальных значений программа выводит максимум 23  .

# lru_cache позволит сэкономить ресурсы компьютера. Функция будет сохранять прошлые значения функций, а значит не придётся считать из заново.
from functools import lru_cache
@lru_cache(None)
def game(first_heap): # Функция игры
    b = 100000000000000000000000000  # В b и c будут записаны результаты определённых ходов, если они возможны
    c = 100000000000000000000000000
    if first_heap <= 11: # Если камней в куче стало меньше или равно 11
        return 0 # Прекращаем игру
    if first_heap % 3 == 0: # Занесём в b значение функции исходя из кратности числа (по условию)
        b = game(first_heap * 2 // 3) # Уберём треть числа
    if first_heap % 2 == 0: # Занесём в с значение функции исходя из кратности числа (по условию)
        c = game(first_heap // 2)
    moves = [game(first_heap - 1)] # Прописываем ходы возможные в партии
    if b != 100000000000000000000000000:
        moves.append(b)
    if c != 100000000000000000000000000:
        moves.append(c)
    petya_win = [i for i in moves if i <= 0]
    if petya_win: # Проверяем есть ли выигрыш Пети в данной позиции
        return -max(petya_win) + 1 # От лица Пети будет выигрыш (положительное число, прибавляем 1, поскольку это будет уже следующий ход)
    else: # Если в данной позиции выигрыш Вани
        return -max(moves) # От лица Пети будет проигрыш (отрицательное число)

for i in range(10, 1000): # Переберём возможные значения (единицу не берём из-за возведения в квадрат, ведь программа будет бесконечной)
    if game(i) == -1: # Если в данной позиции возможен выигрыш Пети первым ходом
        print(i) # Выведем нужное значение

Ответ: 23
Рулетка
Вы можете получить скидку в рулетке!