19.04 Уменьшение количества камней
Ошибка.
Попробуйте повторить позже
Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежит куча камней. Игроки ходят по очереди, первый ход делает Петя. В игре разрешено делать следующие ходы:
– убрать из кучи один камень;
– если количество камней в куче чётно, убрать половину имеющегося количества;
– если количество камней в куче кратно трём, убрать треть имеющегося количества.
Например, если в куче 4 камня, то за один ход можно получить 2 или 3 камня, а если в куче 6 камней, то за один
ход можно получить 3, 4 или 5 камней. Игра завершается, когда количество камней в куче становится меньше 10.
Победителем считается игрок, сделавший последний ход, то есть первым получивший кучу, в которой будет меньше 10
камней. В начале игры в куче было S камней, . Укажите максимальное значение S, при котором Петя не
может выиграть первым ходом, но при любом первом ходе Пети Ваня может выиграть своим первым
ходом.
Решение руками:
Петя должен сделать для Вани такое количество камней, чтобы тот сразу же победил.
Если попалось число не кратное двум и пяти, то игрок обязан вычесть один камень, сделав число как минимум чётным.
Тогда сделаем действия в обратном порядке. Больше всего камней отнимает деление на два, будем делать его от
максимального числа для выигрыша - .
. Значит из 18 Ваня смог бы моментально выиграть. Остаётся добавить единицу, ведь у Пети просто не
будет выбора.
Число определённо нам подходит. Петя уменьшит его на единицу, а Ваня поделит на
, выиграв первым
ходом.
Больше рассматривать смысла нет, ведь мы провернули все действия от максимального победного числа в
обратном порядке. К тому же увеличили его в
раза, что является максимально возможным увеличением за
раз.
Ответ:
Решение программой:
Для решения на Python используем рекурсию с проверкой всех возможных ходов (, делить на
, делить на
),
чтобы определить, чья это выигрышная позиция.
Функция возвращает , если игра уже завершена (камней
), положительное число — если при оптимальной игре
побеждает текущий игрок, и отрицательное – если побеждает соперник.
Так как первый ход делает Петя, цикл запускается от его лица: если значение функции положительное,
выигрывает Петя, а если отрицательное – Ваня. Если функция вернёт - значит Ваня гарантированно
выиграл первым ходом. При переборе возможных начальных значений программа выводит максимум
.
# 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) # Выведем нужное значение
Специальные программы

Программа
лояльности v2.0
Приглашай друзей в Школково и получай вознаграждение до 10%!

Крути рулетку
и выигрывай призы!
Крути рулетку и покупай курсы со скидкой, которая привязывается к вашему аккаунту.

Бесплатное онлайн-обучение
Для школьников из приграничных территорий России, проживающих в ДНР, ЛНР, Херсонской, Запорожской, Белгородской, Курской, Брянской областях и Крыму.

Налоговые вычеты
Узнай, как получить налоговый вычет при оплате обучения в «Школково».

Специальное предложение
для учителей
Бесплатный доступ к любому курсу подготовки к ЕГЭ, ОГЭ и олимпиадам от «Школково». Мы с вами делаем общее и важное дело, а потому для нас очень значимо быть чем-то полезными для учителей по всей России!

Вернём деньги за курс
за твою сотку на ЕГЭ
Сдать экзамен на сотку и получить обратно деньги за подготовку теперь вполне реально!