Допустим, у вас есть 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
Дайте мне знать, если у вас есть какие-либо вопросы или предложения. Удачи и хорошей оптимизации!