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

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

Задача 1#43479

Для правил, описанных в задании 19  известно, что m = 15  и что n > 10  , и при этом первый игрок не при любом начальном количестве камней может играть так, чтобы выиграть (при любой игре второго). Найдите максимальное значение n  .

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

Если при любом количестве камней в куче первый может сделать ход так, чтобы в куче осталось число камней, отличное и от m, и от n, то он победит. Пусть в куче k камней и ход первого. Если k <=  10  , то первый выигрывает одним ходом (вычитая 10, если k = 10  , или 1  , если k <= 9  ). Пусть k > 10  . Первый может оставить в куче либо k − 1  камень, либо k − 10  . Если бы в одном случае получалось m  , а в другом – n  , число |m − n| равнялось бы 9.

Значит, для m = 15  единственное возможное n - это 24.

Ответ: 24

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

Задача 2#43478

Для правил, описанных в задании 19  известно, что S = 20  , m = 2  , n = 3  .

Кто побеждает при правильной игре? В ответе запишите номер игрока.

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

Ходы для каждого из игроков различны, значит стоит рассматривать выигрышные проигрышные позиции для двух игроков. Иначе говоря, считать не стандартные state[x][y], а state[x][y][type]. Анализ позиций приводит к ответу: выигрывает второй. Позиция S = 20, для первого игрока является позицией типа LOSE5

from functools import lru_cache

def h1(n):
    if (n >= 10):
        return n - 1, n - 10
    else:
        return n - 1, n - 1

def h2(n):
    if (n >= 3):
        return n - 2, n - 3
    else:
        return n - 2, n - 2

@lru_cache(None)
def f1(n):
    if (n == 0):
        return ’END’
    if (any(f2(x) == ’END’ for x in h1(n))):
        return ’WIN1’
    if (all(f2(x) == ’WIN1’ for x in h1(n))):
        return ’LOSE1’
    if (any(f2(x) == ’LOSE1’ for x in h1(n))):
        return ’WIN2’
    if (all(f2(x) == ’WIN1’ or f2(x) == ’WIN2’ for x in h1(n))):
        return ’LOSE2’
    if (any(f2(x) == ’LOSE2’ for x in h1(n))):
        return ’WIN3’
    if (all(f2(x) == ’WIN1’ or f2(x) == ’WIN2’ or \
            f2(x) == ’WIN3’ for x in h1(n))):
        return ’LOSE3’
    if (any(f2(x) == ’LOSE3’ for x in h1(n))):
        return ’WIN4’
    if (all(f2(x) == ’WIN1’ or f2(x) == ’WIN2’ \
            or f2(x) == ’WIN3’ or f2(x) == ’WIN4’ for x in h1(n))):
        return ’LOSE4’
    if (any(f2(x) == ’LOSE4’ for x in h1(n))):
        return ’WIN5’
                                                                                                     
                                                                                                     
    if (
            all(f2(x) == ’WIN1’ or f2(x) == ’WIN2’ or f2(x) == ’WIN3’ \
                or f2(x) == ’WIN4’ or f2(x) == ’WIN5’ for x in
                h1(n))):
        return ’LOSE5’
    if (any(f2(x) == ’LOSE5’ for x in h1(n))):
        return ’WIN6’

@lru_cache(None)
def f2(n):
    if (n < 2):
        return ’END’
    if (any(f1(x) == ’END’ for x in h2(n))):
        return ’WIN1’
    if (all(f1(x) == ’WIN1’ for x in h2(n))):
        return ’LOSE1’
    if (any(f1(x) == ’LOSE1’ for x in h2(n))):
        return ’WIN2’
    if (all(f1(x) == ’WIN1’ or f1(x) == ’WIN2’ for x in h2(n))):
        return ’LOSE2’
    if (any(f1(x) == ’LOSE2’ for x in h2(n))):
        return ’WIN3’
    if (all(f1(x) == ’WIN1’ or f1(x) == ’WIN2’ or \
            f1(x) == ’WIN3’ for x in h2(n))):
        return ’LOSE3’
    if (any(f1(x) == ’LOSE3’ for x in h2(n))):
        return ’WIN4’
    if (all(f1(x) == ’WIN1’ or f1(x) == ’WIN2’ or f1(x) == ’WIN3’ or \
            f1(x) == ’WIN4’ for x in h2(n))):
        return ’LOSE4’
    if (any(f1(x) == ’LOSE4’ for x in h2(n))):
        return ’WIN5’
    if (
            all(f1(x) == ’WIN1’ or f1(x) == ’WIN2’ or f1(x) == ’WIN3’ or \
                f1(x) == ’WIN4’ or f1(x) == ’WIN5’ for x in
                h2(n))):
        return ’LOSE5’
    if (any(f1(x) == ’LOSE5’ for x in h2(n))):
        return ’WIN6’
print(f1(20))

 

Ответ: 2

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

Задача 3#43477

Двое играют в следующую игру. Есть кучка, в которой S  камней. Первый каждым своим ходом берет 1  или 10  камней. Второй каждым своим ходом берёт m  или n  камней. Ходят по очереди, начинает первый. Тот, кто не может сделать ход, проигрывает

Известно, что S = 100  , m = 1  , n = 10  .

Кто побеждает при правильной игре? В ответе запишите номер игрока.

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

Ходы симметричны, а значит стратегия дополнения до 11. Первый выигрывает забрав 1 камень.

Ответ: 1

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

Задача 4#30399

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

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

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

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

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

Рассмотрим S = 13.  Из этой позиции Петя может сходить в S = 10  или S = 11,  а из этих позиций Ваня сходит либо в S = 7  , либо в S = 8,  а мы знаем, что это позиции типа LOSE1  .

 

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

from functools import lru_cache


def moves(heap):
    m = []
    if heap % 2 == 0:
        m += [heap // 2]
    else:
        if heap > 1:
            m += [heap - 2]
    if heap % 3 == 0:
        m += [heap // 3]
    else:
        if heap > 2:
            m += [heap - 3]
    return m


@lru_cache(None)
def game(heap):
    if heap <= 2:
        return 0
    steps = [game(x) for x in moves(heap)]
    if any(x % 2 == 0 for x in steps):
        return min(x for x in steps if x % 2 == 0) + 1
    return max(steps) + 1


for s in range(3, 100):
    if game(s) == 4:
        print(s)
        break

Ответ: 13

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

Задача 5#30398

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

В ответе запишите числа в порядке возрастания без пробелов и знаков препинаний.

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

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

Для начала давайте найдём все позиции WIN1  . Это все 3 ≤ S ≤ 6.  Теперь найдём все позиции LOSE1  . Это позиции S = 7,8,12.  Рассмотрим позицию S = 9.  Уменьшение на 2  приведёт нас в S = 7,  а это LOSE1  . Теперь Рассмотрим позицию S = 36.  Уменьшение в 3  раза приведёт нас в S = 12,  а это LOSE1  . Пишем их в ответ.

 

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

from functools import lru_cache


def moves(heap):
    m = []
    if heap % 2 == 0:
        m += [heap // 2]
    else:
        if heap > 1:
            m += [heap - 2]
    if heap % 3 == 0:
        m += [heap // 3]
    else:
        if heap > 2:
            m += [heap - 3]
    return m


@lru_cache(None)
def game(heap):
    if heap <= 2:
        return 0
    steps = [game(x) for x in moves(heap)]
    if any(x % 2 == 0 for x in steps):
        return min(x for x in steps if x % 2 == 0) + 1
    return max(steps) + 1


for s in range(3, 100):
    if game(s) == 3:
        print(s)

Ответ: 936

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

Задача 6#30397

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

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

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

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

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

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

Рассмотрим S = 6.  Первым ходом Петя делает неудачный ход в S = 3,  после чего Ваня убирает из кучи две трети камней, создавая этим позицию S = 1  и побеждая.

 

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

from functools import lru_cache


def moves(heap):
    m = []
    if heap % 2 == 0:
        m += [heap // 2]
    else:
        if heap > 1:
            m += [heap - 2]
    if heap % 3 == 0:
        m += [heap // 3]
    else:
        if heap > 2:
            m += [heap - 3]
    return m


@lru_cache(None)
def game(heap):
    if heap <= 2:
        return 0
    steps = [game(x) for x in moves(heap)]
    if any(x % 2 == 0 for x in steps):
        return min(x for x in steps if x % 2 == 0) + 1
    return max(steps) + 1


for s in range(3, 100):
    print(s, game(s), [game(x) for x in moves(s)])

Ответ: 6

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

Задача 7#30384

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

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

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

Если такого значения нет, в ответ запишите 0.

 

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

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

Рассмотрим позицию (9,20)  :

  1. Если Петя сходит в (9,10)  , то Ваня ответит ходом, ведущим в (9,9)  , а мы знаем, что Петя проигрывает в этой позиции за один ход;
  2. Если Петя сходит в (4,20)  , то Ваня сходит в (3,20)  . Из этой позиции Петя никак не выиграет за один ход, а Ваня победит делением второй кучи;
  3. Если Петя сходит в (8,20)  , то Ваня сходит в (8,10)  . Петя никак не выиграет за 1  ход, а Ваня выиграет делением второй кучи;
  4. Если Петя сходит в (9,19)  , то Ваня сходит в (9,9)  . Петя не выигрывает за 1  ход, а Ваня побеждает делением второй кучи.

 

Решение Excel

PIC PIC

Для решения используем табличку, которую сделали для решения 20 задачи.

Добавляем новый столбец Ваня (второй ход Вани).

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

Перепишем формулы в ячейках, отвечающих за первый ход Пети, так, чтобы не было повторов.

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

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

 

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

from functools import lru_cache


def moves(heap):
    a, b = heap
    m = []
    if a >= 1:
        m += [(a - 1, b), (a // 2, b)]
    if b >= 1:
        m += [(a, b - 1), (a, b // 2)]
    return m


@lru_cache(None)
def game(heap):
    if sum(heap) <= 12:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’P1’
    elif all(game(x) == ’P1’ for x in moves(heap)):
        return ’V1’
    elif any(game(x) == ’V1’ for x in moves(heap)):
        return ’P2’
    elif all(game(x) == ’P1’ or game(x) == ’P2’ for x in moves(heap)):
        return ’V2’


for s in range(100, 3, -1):
    if game((9, s)) == ’V2’:
        print(s)
        break

Ответ: 20

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

Задача 8#30383

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

Если такого значения нет, в ответ запишите 0.

 

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

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

Мы знаем, что позиция (9,9)  – это позиция LOSE1  . Значит все позиции, которые ведут в эту, являются WIN2 . Нам подойдут значения S = 18  и S = 19  (18∕2 = 9 и 19∕2 = 9  ). Значит нам подойдёт значение 19  .

 

Решение Excel

PIC

Для решения используем табличку, которую сделали для решения 19 задачи.

Добавляем новый столбик — Петя (второй ход Пети).

Вырезаем имеющиеся числовые значения из таблички и вставляем их в ячейку E4  , в неё же записываем =B4-1, а в F4 — =С4

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

Копируем полученную таблицу в вставляем её три раза. Меняем первые ходы Пети, чтобы не было повторов.

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

 

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

from functools import lru_cache


def moves(heap):
    a, b = heap
    m = []
    if a >= 1:
        m += [(a - 1, b), (a // 2, b)]
    if b >= 1:
        m += [(a, b - 1), (a, b // 2)]
    return m


@lru_cache(None)
def game(heap):
    if sum(heap) <= 12:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’P1’
    elif all(game(x) == ’P1’ for x in moves(heap)):
        return ’V1’
    elif any(game(x) == ’V1’ for x in moves(heap)):
        return ’P2’
    elif all(game(x) == ’P1’ or game(x) == ’P2’ for x in moves(heap)):
        return ’V2’


for s in range(100, 3, -1):
    if game((9, s)) == ’P2’:
        print(s)
        break

Ответ: 19

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

Задача 9#30382

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать из одной из куч один камень или уменьшить количество камней в куче в два раза (если количество камней в куче нечётно, остаётся на 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


def moves(heap):
    a, b = heap
    m = []
    if a >= 1:
        m += [(a - 1, b), (a // 2, b)]
    if b >= 1:
        m += [(a, b - 1), (a, b // 2)]
    return m


@lru_cache(None)
def game(heap):
    if sum(heap) <= 12:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’P1’
    elif all(game(x) == ’P1’ for x in moves(heap)):
        return ’V1’
    elif any(game(x) == ’V1’ for x in moves(heap)):
        return ’P2’
    elif all(game(x) == ’P1’ or game(x) == ’P2’ for x in moves(heap)):
        return ’V2’


for s in range(100, 3, -1):
    if game((9, s)) == ’V1’:
        print(s)

Ответ: 9

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

Задача 10#30381

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

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

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

Если такого значения нет, в ответ запишите 0.

 

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

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

Мы знаем, что S = 11  и S = 14  это позиции WIN2  . Рассмотрим позицию 15  . Все ходы из неё ведут в WIN2  , значит это позиция LOSE2  .

 

Решение Excel

PIC

Для решения используем табличку, которую сделали для решения 20 задачи.

Добавляем новый столбец — Ваня (второй ход Вани).

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

Перепишем формулы в ячейках, отвечающих за первый ход Пети. В первую запишем =B4-1, а во вторую — =B4-3.

Теперь добавим условное форматирование для первого хода Пети: мы их сделаем красными (в разделе Главная выберем условное форматирование ⇒ Правила выделения ячеек ⇒ Меньше…, в открывшемся окошке записываем 8  и выбираем красный цвет).

Осталось подставить значения в ячейку Старт. Если после одного хода Пети Ваня может победить вторым (то есть у Пети не будет красных ячеек после второго хода) и/или после другого Ваня может победить первым ходом, то данное значение нам подходит, и его нужно записать в ответ.

 

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

from functools import lru_cache


def moves(heap):
    m = []
    if heap >= 1:
        m += [heap - 1]
    if heap >= 3:
        m += [heap - 3]
    return m


@lru_cache(None)
def game(heap):
    if heap <= 7:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’P1’
    elif all(game(x) == ’P1’ for x in moves(heap)):
        return ’V1’
    elif any(game(x) == ’V1’ for x in moves(heap)):
        return ’P2’
    elif all(game(x) == ’P1’ or game(x) == ’P2’ for x in moves(heap)):
        return ’V2’


for s in range(100, 7, -1):
    if game(s) == ’V2’:
        print(s)
        break

Ответ: 15

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

Задача 11#30380

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

 

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

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

Очевидно, что при S ≤ 10  Петя выигрывает за один ход. Значит при S = 11  Ваня проигрывает за один ход — это позиция LOSE1  . При S = 12  и S = 14  Петя сходит в 11  и победит за 2  хода. Ответ 2  .

 

Решение Excel

PIC PIC

Для решения используем табличку, которую сделали для решения 19 задачи.

Добавляем новый столбец — Петя (второй ход Пети).

Вырезаем имеющиеся числовые значения из таблички и вставляем их в ячейку D4  , далее копируем эти же числовые значения и вставляем их в ячейку D7  .

В D4  пишем формулу =В4-1, а в D7  — =B4-3

Теперь добавим условное форматирование. Все ячейки, относящиеся к первому столбику Петя мы окрасим зелёным (в разделе Главная выберем условное форматирование ⇒ Правила выделения ячеек ⇒ Меньше…, в открывшемся окошке записываем 8  и выбираем зелёный цвет).

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

 

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

from functools import lru_cache


def moves(heap):
    m = []
    if heap >= 1:
        m += [heap - 1]
    if heap >= 3:
        m += [heap - 3]
    return m


@lru_cache(None)
def game(heap):
    if heap <= 7:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’P1’
    elif all(game(x) == ’P1’ for x in moves(heap)):
        return ’V1’
    elif any(game(x) == ’V1’ for x in moves(heap)):
        return ’P2’
    elif all(game(x) == ’P1’ or game(x) == ’P2’ for x in moves(heap)):
        return ’V2’


count = 0
for s in range(100, 7, -1):
    if game(s) == ’P2’:
        count += 1
print(count)

Ответ: 2

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

Задача 12#30379

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

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

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

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

 

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

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

Очевидно, что Петя должен «сглупить», чтобы изначальная позиция была максимальной.

Значит S − 3− 3 ≤ 7 ⇒ S ≤ 13 ⇒ S = 13.

 

Решение Excel

PIC

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

В первую ячейку в столбце Петя записываем формулу =B4-1. Далее из полученного значения рассматриваем ходы Вани и, соответственно, записываем формулу в ячейки столбца Ваня =J4-3 (рассматриваем только один ход, так как Ване выгоднее всего вычесть как можно больше камней, чтобы точно победить, если это возможно в данном случае).

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

Скопируем табличку с первого хода Пети по второй ход Пети без заголовков и вставим её копию чуть ниже первой, теперь заменим формулу в первом ходе Пети на =B4-3.

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

 

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

from functools import lru_cache


def moves(heap):
    m = []
    if heap >= 1:
        m += [heap - 1]
    if heap >= 3:
        m += [heap - 3]
    return m


@lru_cache(None)
def game(heap):
    if heap <= 7:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’P1’
    elif any(game(x) == ’P1’ for x in moves(heap)):
        return ’V1’
    elif any(game(x) == ’V1’ for x in moves(heap)):
        return ’P2’
    elif all(game(x) == ’P1’ or game(x) == ’P2’ for x in moves(heap)):
        return ’V2’


for s in range(100, 7, -1):
    if game(s) == ’V1’:
        print(s)
        break

Ответ: 13

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

Задача 13#26100

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

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

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

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

def moves(h):
    a, b = h
    if a > 1 and b > 1:
        return (a - 1, b), (a, b - 1), (a // 2 + (a % 2), b), (a, b // 2 + (b % 2))
    if a > 1:
        return (a - 1, b), (a, b - 1), (a // 2 + (a % 2), b)
    if b > 1:
        return (a - 1, b), (a, b - 1), (a, b // 2 + (b % 2))
    return (a - 1, b), (a, b - 1)

@lru_cache(None)
def f(h):
    if sum(h) <= 32:
        return ’END’
    if any(f(x) == ’END’ for x in moves(h)):
        return ’WIN1’
    if all(f(x) == ’WIN1’ for x in moves(h)):
        return ’LOSE1’
    if any(f(x) == ’LOSE1’ for x in moves(h)):
        return ’WIN2’
    if all(f(x) == ’WIN1’ or f(x) == ’WIN2’ for x in moves(h)):
        return ’LOSE2’

for i in range(23, 100):
    h = i, 10
    if f(h) == ’LOSE2’:
        print(i)

Ответ: 48

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

Задача 14#26099

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

– Петя не может выиграть за один ход;

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

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

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

def moves(h):
    a, b = h
    if a > 1 and b > 1:
        return (a - 1, b), (a, b - 1), (a // 2 + (a % 2), b), (a, b // 2 + (b % 2))
    if a > 1:
        return (a - 1, b), (a, b - 1), (a // 2 + (a % 2), b)
    if b > 1:
        return (a - 1, b), (a, b - 1), (a, b // 2 + (b % 2))
    return (a - 1, b), (a, b - 1)

@lru_cache(None)
def f(h):
    if sum(h) <= 32:
        return ’END’
    if any(f(x) == ’END’ for x in moves(h)):
        return ’WIN1’
    if all(f(x) == ’WIN1’ for x in moves(h)):
        return ’LOSE1’
    if any(f(x) == ’LOSE1’ for x in moves(h)):
        return ’WIN2’

minim = 100000
maxim = 0
for i in range(23, 100):
    h = i, 10
    if f(h) == ’WIN2’:
        minim = min(minim, i)
        maxim = i
print(minim, maxim)

Ответ: 46 90

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

Задача 15#26098

Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя. За один ход игрок может убрать из одной из куч один камень или уменьшить количество камней в куче в два раза (если количество камней в куче нечётно, остаётся на 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

def moves(h):
    a, b = h
    if a > 1 and b > 1:
        return (a - 1, b), (a, b - 1), (a // 2 + (a % 2), b), (a, b // 2 + (b % 2))
    if a > 1:
        return (a - 1, b), (a, b - 1), (a // 2 + (a % 2), b)
    if b > 1:
        return (a - 1, b), (a, b - 1), (a, b // 2 + (b % 2))
    return (a - 1, b), (a, b - 1)

@lru_cache(None)
def f(h):
    if sum(h) <= 32:
        return ’END’
    if any(f(x) == ’END’ for x in moves(h)):
        return ’WIN1’
    if all(f(x) == ’WIN1’ for x in moves(h)):
        return ’LOSE1’

for i in range(23, 100):
    h = i, 10
    if f(h) == ’LOSE1’:
        print(i)

Ответ: 45

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

Задача 16#23804

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

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

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

Если такого значения нет, в ответ запишите 0.

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

def moves(heap):
    a, b, c = heap
    m = []
    if a > 1:
        m += [(a - 1, b, c), ((a + 1) // 2, b, c)]
    if b > 1:
        m += [(a, b - 1, c), (a, (b + 1) // 2, c)]
    if c > 1:
        m += [(a, b, c - 1), (a, b, (c + 1) // 2)]
    return m

@lru_cache(None)
def game(heap):
    if sum(heap) <= 32:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’WIN1’
    elif all(game(x) == ’WIN1’ for x in moves(heap)):
        return ’LOSE1’
    elif any(game(x) == ’LOSE1’ for x in moves(heap)):
        return ’WIN2’
    elif all(game(x) == ’WIN1’ or game(x) == ’WIN2’ for x in moves(heap)):
        return ’LOSE2’

for s in range(12, 100):
    if game((11, 11, s)) == ’LOSE2’:
        print(s)

Ответ: 24

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

Задача 17#23803

Для игры, описанной в предыдущем задании, найдите количество таких значений S  , при которых у Наруто есть выигрышная стратегия, причём Наруто не может выиграть за один ход и Наруто может выиграть своим вторым ходом независимо от того, как будет ходить Саске.

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

def moves(heap):
    a, b, c = heap
    m = []
    if a > 1:
        m += [(a - 1, b, c), ((a + 1) // 2, b, c)]
    if b > 1:
        m += [(a, b - 1, c), (a, (b + 1) // 2, c)]
    if c > 1:
        m += [(a, b, c - 1), (a, b, (c + 1) // 2)]
    return m

@lru_cache(None)
def game(heap):
    if sum(heap) <= 32:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’WIN1’
    elif all(game(x) == ’WIN1’ for x in moves(heap)):
        return ’LOSE1’
    elif any(game(x) == ’LOSE1’ for x in moves(heap)):
        return ’WIN2’

count = 0
for s in range(12, 100):
    count += (game((11, 11, s)) == ’WIN2’)
print(count)

Ответ: 5

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

Задача 18#23802

Два игрока, Наруто и Саске, играют в следующую игру. Перед игроками лежат три кучи кунаев. Игроки ходят по очереди, первый ход делает Наруто. За один ход игрок может убрать из одной из куч один кунай или уменьшить количество кунаев в куче в два раза (если количество кунаев в куче нечётно, остаётся на 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

def moves(heap):
    a, b, c = heap
    m = []
    if a > 1:
        m += [(a - 1, b, c), ((a + 1) // 2, b, c)]
    if b > 1:
        m += [(a, b - 1, c), (a, (b + 1) // 2, c)]
    if c > 1:
        m += [(a, b, c - 1), (a, b, (c + 1) // 2)]
    return m

@lru_cache(None)
def game(heap):
    if sum(heap) <= 32:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’WIN1’
    elif any(game(x) == ’WIN1’ for x in moves(heap)):
        return ’LOSE1’

for s in range(100, 11, -1):
    if game((11, 11, s)) == ’LOSE1’:
        print(s)
        break

Ответ: 40

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

Задача 19#23713

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

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

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

Если такого значения нет, в ответ запишите 0.

Показать ответ и решение
from functools import lru_cache
def moves(heap):
    m = []
    if heap > 0:
        m += [heap - 1]
    if heap > 2:
        m += [heap - 3]
    return m
@lru_cache(None)
def game(heap):
    if heap <= 11:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’WIN1’
    elif all(game(x) == ’WIN1’ for x in moves(heap)):
        return ’LOSE1’
    elif any(game(x) == ’LOSE1’ for x in moves(heap)):
        return ’WIN2’
    elif all(game(x) == ’WIN1’ or game(x) == ’WIN2’ for x in moves(heap)):
        return ’LOSE2’
for s in range(12, 100):
    print(s, game(s))
# или
from functools import lru_cache
def moves(heap):
    m = []
    if heap > 0:
        m += [heap - 1]
    if heap > 2:
        m += [heap - 3]
    return m
@lru_cache(None)
def game(heap):
    if heap <= 11:
        return 0
    steps = [game(x) for x in moves(heap)]
    if any(x % 2 == 0 for x in steps):
        return min(x for x in steps if x % 2 == 0) + 1
    return max(steps) + 1
                                                                                                     
                                                                                                     
for s in range(1, 100):
    print(s, game(s), [game(x) for x in moves(s)])

Ответ: 19

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

Задача 20#23712

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

В ответе запишите числа в порядке возрастания без пробелов и знаков препинания.

Показать ответ и решение
from functools import lru_cache
def moves(heap):
    m = []
    if heap > 0:
        m += [heap - 1]
    if heap > 2:
        m += [heap - 3]
    return m
@lru_cache(None)
def game(heap):
    if heap <= 11:
        return ’END’
    elif any(game(x) == ’END’ for x in moves(heap)):
        return ’WIN1’
    elif all(game(x) == ’WIN1’ for x in moves(heap)):
        return ’LOSE1’
    elif any(game(x) == ’LOSE1’ for x in moves(heap)):
        return ’WIN2’
    elif all(game(x) == ’WIN1’ or game(x) == ’WIN2’ for x in moves(heap)):
        return ’LOSE2’
for s in range(12, 100):
    print(s, game(s))
# или
from functools import lru_cache
def moves(heap):
    m = []
    if heap > 0:
        m += [heap - 1]
    if heap > 2:
        m += [heap - 3]
    return m
@lru_cache(None)
def game(heap):
    if heap <= 11:
        return 0
    steps = [game(x) for x in moves(heap)]
    if any(x % 2 == 0 for x in steps):
        return min(x for x in steps if x % 2 == 0) + 1
    return max(steps) + 1
                                                                                                     
                                                                                                     
for s in range(1, 100):
    print(s, game(s), [game(x) for x in moves(s)])

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