Как изменить решение для подсчёта сумм и комбинаций игральных кубиков, если количество кубиков параметр?
Что проверяют
Умеете ли вы уйти от вложенных циклов, число которых зашито в код, к решению, где количество костей это просто параметр. Для двух костей хватает двойного цикла, для n нужна рекурсия или динамическое программирование. Следом почти всегда просят оценить сложность и перейти от числа исходов к вероятностям.
Как отвечать
Сначала уточните постановку: считать упорядоченные исходы, где (1, 2) и (2, 1) разные, или неупорядоченные наборы. Для распределения сумм нужны упорядоченные.
- перебор:
itertools.product(range(1, k + 1), repeat=n)даётk^nисходов. Годится только как эталон для проверки на маленькихn; - динамика по костям:
dp[i][s]это число способов набрать суммуsнаiкостях,dp[i][s] = dp[i-1][s-1] + ... + dp[i-1][s-k], стартdp[0][0] = 1. Хватает двух строк, каждую итерацию считаете в новый массив; - сложность: сумм порядка
n·k, на каждуюkслагаемых, итогоO(n²·k²). Скользящая сумма по окну изkэлементов убирает один множительk; - свёртка: распределение
nкостей этоn-кратная свёртка вектора изkединиц. В NumPy это цикл изnp.convolve, для больших размеров свёртка через FFT; - вероятности: делите на
k^nили сразу храните вероятности вместо счётчиков. Число исходов растёт экспоненциально, иint64в NumPy переполнится примерно на трёх десятках шестигранных костей, а питоновскиеintпросто замедлятся; - проверка: среднее суммы
n·(k+1)/2, дисперсияn·(k²-1)/12, при большомnраспределение близко к нормальному. Сверьтесь с симуляцией черезnp.random.default_rng().integers.
Неупорядоченных наборов C(n+k-1, n), их перечисляет itertools.combinations_with_replacement.
Где спотыкаются
Оставляют перебор и не видят экспоненты: у десяти шестигранных костей уже больше 60 миллионов исходов.
Обновляют массив на месте, не обнуляя старые значения. Тогда в ответ подмешиваются броски с меньшим числом костей, и счётчики получаются завышенными.
Недооценивают сложность: пишут O(n·k²), забыв, что диапазон сумм сам растёт вместе с n.