Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может добавить в кучу три камня или пять камней или увеличить количество камней в куче в два раза. У каждого игрока, чтобы делать ходы, есть неограниченное количество камней. Игра завершается в тот момент, когда количество камней в куче становится не менее 67. Победителем считается игрок, сделавший последний ход, то есть первым получивший кучу, в которой будет 67 или больше камней. В начальный момент в куче было S камней, .
Найдите минимальное значение S, при котором Ваня выигрывает своим первым ходом при любой игре Пети?
Решение руками
Для начала определим значения, при которых Петя побеждает первым ходом. Максимальный ход доступный нам в партии это . Минимальное значение отрезка значений, в которых Петя побеждает первым ходом равняется:
(округляем в большую сторону) =
Получается, что в отрезке [34;66] Петя выигрывает своим первым ходом. Теперь определим значение, в котором Ваня побеждает своим первым ходом. Значение, из которого ВСЕ ходы ведут в вышеописанный отрезок – это значение, в котором Ваня выигрывает своим первым ходом. Распишем значение и стратегии, при которых Ваня побеждает первым ходом:
. Петя может увеличить количество камней до
,
или
камней. Во всех этих случаях Ване не составит труда завершить партию следующим ходом.
. Петя может увеличить количество камней до
,
или
камней. Во всех этих случаях Ване не составит труда завершить партию следующим ходом.
. Петя может увеличить количество камней до
,
или
камней. Во всех этих случаях Ване не составит труда завершить партию следующим ходом.
В ответ нужно указать минимальное значение S. Ответ:
Решение БУ
from functools import lru_cache
@lru_cache(None)
def game(first_heap): # функция игры
if first_heap >= 67: # если камней в куче стало больше 66
return 0 # прекращаем игру
moves = [game(first_heap+3),game(first_heap+5),game(first_heap*2)] # расписываем ходы доступные нам в партии
petya_win = [i for i in moves if i <= 0]
if petya_win: # проверяем есть ли выигрыш Пети в данной позиции
return -max(petya_win) + 1
else: # если в данной позиции выигрыш Вани
return -max(moves)
count = 0
for i in range(1,67):
if game(i) == -1: # если в данной позиции возможен выигрыш Вани первым ходом
print(i)
break