Текстовые решения некоторых заданий

1. Демоверсия 2023

1.2. Программное решение

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

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

В начальный момент в куче было S камней, 1 ≤ S ≤ 128.

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

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

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

#Функция принимает 2 значения
#x - кол-во камней на текущей момент
#n - кол-во прошедших ходов
def f3(x,n):
    #Если еще никто не ходил
    if(n==0):
        #Ходит Петя
        #1й вариант добавить 1 камень
        v1=f3(x+1,n+1)
        #2й вариант увеличить количество камней в 2 раза
        v2=f3(x*2,n+1)
        #Если и v1, и v2 приводит Ваню к победе
        #то это удовлетворительный для нас результат
        return v1 and v2
    #Если только что сходил Петя
    elif(n==1):
        #Если он выиграл
        if(x>=129):
            #это неудовлетворительный результат
            return False
        #Если он не выиграл
        else:
            #то у Вани те же 2 варианта как сходить
            #1й вариант добавить 1 камень
            v1=f3(x+1,n+1)
            #2й вариант увеличить количество камней в 2 раза
            v2=f3(x*2,n+1)
            #Если v1 или v2 приводит Ваню к победе
            #то это удовлетворительный для нас результат
            return v1 or v2
    #Если только что сходил Ваня
    elif(n==2):
        #Если он выиграл
        if(x>=129):
            #это удовлетворительный результат
            return True
        #Если он не выиграл
        else:
            #то у Пети те же 2 варианта как сходить
            #1й вариант добавить 1 камень
            v1=f3(x+1,n+1)
            #2й вариант увеличить количество камней в 2 раза
            v2=f3(x*2,n+1)
            #Если и v1, и v2 приводит Ваню к победе
            #то это удовлетворительный для нас результат
            return v1 and v2
    #Если только что сходил Петя второй раз
    elif(n==3):
        #Если он выиграл
        if(x>=129):
            #это неудовлетворительный результат
            return False
        #Если он не выиграл
        else:
            #то у Вани те же 2 варианта как сходить
            #1й вариант добавить 1 камень
            v1=f3(x+1,n+1)
            #2й вариант увеличить количество камней в 2 раза
            v2=f3(x*2,n+1)
            #Если v1 или v2 приводит Ваню к победе
            #то это удовлетворительный для нас результат
            return v1 or v2
    #Если только что сходил Ваня второй раз
    elif(n==4):
        #Если он выиграл
        if(x>=129):
            #это удовлетворительный результат
            return True
        #Если он выиграть не смог, то
        #игра уже слишком затянулась
        else:
            #и это неудовлетворительный результат
            return False

#Переберем начальное кол-во камней
for S in range(1,129):
    #Если при таком кол-ве камней
    #в самом начале игры мы получаем
    #удовлетворительный результат
    if(f3(S,0)):
        #То выводим начальное кол-во
        #камней при котором это произошло
        print(S)

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

#Функция принимает 2 значения
#x - кол-во камней на текущей момент
#n - кол-во прошедших ходов
def f4(x,n):
    #Если еще никто не ходил
    if(n==0):
        #Ходит Петя
        #1й вариант добавить 1 камень
        v1=f4(x+1,n+1)
        #2й вариант увеличить количество камней в 2 раза
        v2=f4(x*2,n+1)
        #Если Ваня сможет победить как при v1, так и при v2,
        #то это удовлетворительный для нас результат
        return v1 and v2
    #Если только что сходил Петя
    elif(n==1):
        #Если он выиграл
        if(x>=129):
            #это неудовлетворительный результат
            return False
        #Если он не выиграл
        else:
            #то у Вани те же 2 варианта как сходить
            #1й вариант добавить 1 камень
            v1=f4(x+1,n+1)
            #2й вариант увеличить количество камней в 2 раза
            v2=f4(x*2,n+1)
            #Если v1 или v2 приводит Ваню к победе
            #то это удовлетворительный для нас результат
            return v1 or v2
    #Если только что сходил Ваня
    elif(n==2):
        #Если он выиграл
        if(x>=129):
            #это удовлетворительный результат
            return True
        #Если он выиграть не смог, то
        #игра уже слишком затянулась
        else:
            #и это неудовлетворительный результат
            return False

#Переберем начальное кол-во камней
for S in range(1,129):
    #Если при таком кол-ве камней
    #в самом начале игры мы получаем
    #удовлетворительный результат
    if(f4(S,0)):
        #То выводим начальное кол-во
        #камней при котором это произошло
        print(S)

Первая программа выводит 62 и 64, вторая программа выводит 64. В ответ идет то число, которое было выведено первой программой, но не было выведено второй.

Ответ: 62.