Допустим, у вас есть 20-гранный кубик. Вы начинаете бросать этот кубик и должны бросить его несколько десятков раз, прежде чем наконец бросить все 20 значений. Вы задаетесь вопросом, сколько рулонов мне нужно, чтобы получить 50% шанс увидеть все 20 значений? И сколько бросков n
кубика с одной стороны мне нужно бросить, прежде чем я переверну все n
стороны?
После некоторого исследования вы обнаружите, что существует формула для расчета вероятности броска всех n
значений после r
бросков.
P(r, n) = n! * S(r, n) / n**r
где S(a, b)
обозначает числа Стирлинга второго рода , количество способов разбить набор из n объектов (каждый рулон) на k непустых подмножеств (каждая сторона).
Вы также найдете последовательность OEIS , которую мы назовем R(n)
, которая соответствует наименьшей, r
где она P(r, n)
составляет не менее 50%. Задача состоит в том, чтобы n
как можно быстрее вычислить й член этой последовательности.
Соревнование
- Учитывая
n
, найти наименьшее,r
гдеP(r, n)
больше или равно0.5
или 50%. - Ваш код теоретически должен обрабатывать любое неотрицательное целое число в
n
качестве входных данных, но мы будем тестировать ваш код только в диапазоне1 <= n <= 1000000
. - Для озвучивания, мы будем принимать общее время , необходимое для запуска
R(n)
на входах1
через10000
. - Мы проверим правильность ваших решений, запустив нашу версию of
R(n)
на вашем выводе, чтобы увидеть, еслиP(your_output, n) >= 0.5
иP(your_output - 1, n) < 0.5
, т.е. что ваш вывод на самом деле является наименьшимr
для данногоn
. - Вы можете использовать любое определение для
S(a, b)
вашего решения. В Википедии есть несколько определений, которые могут быть полезны здесь. - Вы можете использовать встроенные модули в своих решениях, включая те, которые рассчитывают
S(a, b)
, или даже те, которые рассчитываютP(r, n)
напрямую. - Вы можете жестко закодировать до 1000 значений
R(n)
и миллион чисел Стирлинга, хотя ни одно из них не является жестким ограничением, и его можно изменить, если вы сможете убедительно аргументировать их повышение или понижение. - Вам не нужно проверять все возможные
r
промежутки междуn
тем,r
что мы ищем, но вам нужно найти самое маленькое,r
а не толькоr
где- нибудьP(r, n) >= 0.5
. - Ваша программа должна использовать язык, который можно свободно запускать в Windows 10.
Спецификации компьютера, на котором будут проверяться ваши решения, таковы i7 4790k, 8 GB RAM
. Спасибо @DJMcMayhem за предоставление его компьютера для тестирования. Не стесняйтесь добавлять свои неофициальные сроки для справки, но официальное время будет предоставлено позже, как только диджей сможет его протестировать.
Контрольные примеры
n R(n)
1 1
2 2
3 5
4 7
5 10
6 13
20 67 # our 20-sided die
52 225 # how many cards from a huge uniformly random pile until we get a full deck
100 497
366 2294 # number of people for to get 366 distinct birthdays
1000 7274
2000 15934
5000 44418
10000 95768
100000 1187943
1000000 14182022
Дайте мне знать, если у вас есть какие-либо вопросы или предложения. Удачи и хорошей оптимизации!