Вычислить произведение a * b ** 2 * c ** 3... эффективно
Каков наиболее эффективный способ вычисления продукта
a 1 b 2 c 3 d 4 e 5...
Предполагая, что квадрат стоит примерно вдвое меньше, чем умножение? Число операндов меньше 100.
Существует ли простой алгоритм и для случая, когда время умножения пропорционально квадрату длины операнда (как при java.math.BigInteger
)?
Первый (и единственный) ответ идеален w.r.t. количество операций.
Как ни странно, при применении к значимым BigInteger
s эта часть вообще не имеет значения. Даже вычисления abbcccddddeeeee без каких-либо оптимизаций занимают одно и то же время.
Большую часть времени тратится на окончательное умножение (BigInteger
реализует ни один из умных алгоритмов, таких как Карацуба, Тоом-Кук или БПФ, поэтому время квадратично). Важно то, что промежуточные мультипликаторы имеют одинаковую величину, т.е. Заданные числа p, q, r, s примерно того же размера, вычисляя (pq) (rs) обычно быстрее, чем ((pq) r) s. Коэффициент скорости, по-видимому, составляет около 1: 2 для некоторых десятков операндов.
Ответы
Ответ 1
Я абсолютно не знаю, является ли это оптимальным подходом (хотя я думаю, что он асимптотически оптимален), но вы можете сделать все это в умножениях O(N)
. Вы группируете аргументы a * b^2 * c^3
следующим образом: c * (c*b) * (c*b*a)
. В псевдокоде:
result = 1
accum = 1
for i in 0 .. arguments:
accum = accum * arg[n-i]
result = result * accum
Я думаю, что это асимптотически оптимально, потому что вам нужно использовать умножения N-1
только для умножения входных аргументов N
.