Собесов

Логика — 100 мудрецов и 3 цвета колпаков: спасти максимум

Статистика и теорверЛогика и стратегииСложнаяSenior

Условие

100 мудрецов выстроены в колонну. На каждом колпак одного из 3 цветов. Каждый видит цвета колпаков впереди стоящих (но не свой и не задних). По очереди (начиная с задного) каждый называет цвет своего колпака; всех слышат. Кто не угадал — казнён.

Придумайте стратегию, спасающую максимум мудрецов гарантированно.

Подсказка: используйте остатки от деления на 3.

Решение

Идея

Сопоставим цветам числа: белый = 0, синий = 1, красный = 2. Тогда сумма «цветов» — это число по модулю 3.

Стратегия

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

Он считает сумму чисел всех 99 видимых колпаков по модулю 3 и называет цвет, соответствующий этому остатку. Например, если сумма = 47, то 47 mod 3 = 2, он говорит «красный».

Его собственный цвет угадан с вероятностью 1/3.

Что делает 2-й (99-й сзади)

Он видит впереди 98 колпаков. Знает:

  • Сумма всех 99 (своего + видимых) по модулю 3 = что сказал первый.
  • Сумма 98 видимых.

Значит, его цвет = (сумма_первого - сумма_98) mod 3. Он называет этот цвет — гарантированно правильный.

Что делает 3-й

Он слышал ответы 1-го и 2-го. Знает:

  • Свой цвет + цвет 2-го + сумма 97 видимых = сумма_первого mod 3.
  • Сумма 97 видимых ему известна.
  • Цвет 2-го — его слышали.

Решает уравнение → знает свой цвет. Гарантированно правильно.

Итог

Мудрецы 2..100 спасены гарантированно — 99 мудрецов. Мудрец 1 — с вероятностью 1/3.

Ожидаемое число выживших: 99 + 1/3 ≈ 99.33.

Обобщение

Для k цветов и n мудрецов спасают n − 1 гарантированно (используют остатки по модулю k).

Псевдокод

# Сторона казни:
def sage_1_speak(visible_99):
    s = sum(visible_99) % 3
    return color_by_number(s)   # например 'красный'
 
def sage_i_speak(i, prev_answers, visible):
    # prev_answers — что сказали с 1-го по (i-1)-й
    # visible — цвета колпаков 100-i впереди стоящих
    parity_announced = number_of(prev_answers[0])     # что сообщил первый
    sum_so_far = sum(prev_answers[1:])                # цвета 2..i-1, угаданные точно
    sum_visible = sum(visible)                        # цвета i+1..100
    my_color = (parity_announced - sum_so_far - sum_visible) % 3
    return color_by_number(my_color)

Подводные камни

  1. «Спасти всех 100» — невозможно: первый мудрец не имеет информации о своём колпаке.
  2. Стратегия «один говорит цвет следующего» — спасает половину; не оптимально.
  3. Только 2 цвета — известная задача, тоже через сумму mod 2 (чётность). 3 цвета — обобщение.
  4. Не каждый «слышит всех» — в задаче подразумевается, что слышат всех; иначе стратегия рушится.

Эталонный ответ

Гарантированно спасаются 99 мудрецов, первый — с вероятностью 1/3.

Кодируем цвета числами 0, 1, 2. Первый мудрец называет цвет, соответствующий сумме mod 3 всех видимых им 99 колпаков. Каждый последующий вычисляет свой цвет, зная объявленную сумму и слышимые ответы.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти