Поскольку ответ Алекса отмечает, есть комбинаторная формула для этого:
В этой формуле p является сумма выпавших чисел (X в вашем вопросе), n - количество кубиков, а s - количество сторон каждой кости (6 в вашем вопросе). Независимо от того, оцениваются ли биномиальные коэффициенты с использованием циклов или предварительно вычисляются с использованием треугольника Pascal, в любом случае сложность времени равна O (n 2 ), если мы возьмем s = 6 в качестве константы и X - n быть O (n).
Вот альтернативный алгоритм, который вычисляет все вероятности одновременно. Идея состоит в том, чтобы использовать дискретную свертку для вычисления распределения суммы двух случайных величин с учетом их распределений. Используя подход «разделяй и властвуй», как в возведении в степень при возведении в квадрат алгоритма , нам нужно только выполнить O (log n) сверток.
Псевдокод находится ниже; sum_distribution(v, n)
возвращает массив, где значение в индексе X - n является числом комбинаций, в которых сумма n
бросков костей равна X.
// for exact results using integers, let v = [1, 1, 1, 1, 1, 1]
// and divide the result through by 6^n afterwards
let v = [1/6.0, 1/6.0, 1/6.0, 1/6.0, 1/6.0, 1/6.0]
sum_distribution(distribution, n)
if n == 0
return [1]
else if n == 1
return v
else
let r = convolve(distribution, distribution)
// the division here rounds down
let d = sum_distribution(r, n / 2)
if n is even
return d
else
return convolve(d, v)
Свертка не может быть выполнена за линейное время, поэтому во время выполнения преобладает последняя свертка на двух массивах длиной 3n, поскольку другие свертки находятся на достаточно более коротких массивах.
Это означает, что если вы используете простой алгоритм свертки, он должен принимать O (n 2 ) время для вычисления всех вероятностей, и если вы используете быстрое преобразование Фурье , тогда это займет O (n log n) времени.