Официальное решение - просто неэффективная реализация повторного вычитания, которая заменяет простое вычитание более сложным умножением; если вы собираетесь использовать повторное вычитание, вы должны хотя бы избавиться от умножения:
def divide(num, div):
quot = 0
while div <= num:
quot += 1
num -= div
return quot, num
Повторное вычитание не «оптимизировано для скорости», как вы увидите, если позвоните divide(1000000000,3)
. Вместо этого мы могли бы использовать повторное вычитание квадратов делителя, или квадратов квадратов делителя, или ..., продолжая до тех пор, пока квадрат квадрата ... делителя не превысит число. В качестве примера рассмотрим проблему divide(1000000000,3)
, упомянутую выше. Сначала мы составим список квадратов:
3 * 3 = 9
9 * 9 = 81
81 * 81 = 6561
6561 * 6561 = 43046721
Мы останавливаемся там, потому что следующий квадрат превышает цель. Теперь мы вызываем наивный алгоритм деления на повторные вычитания повторно для каждого остатка:
divide(1000000000, 43046721) = (23, 9925417)
divide(9925417, 6561) = (1512, 5185)
divide(5185, 81) = (64, 1)
divide(1, 9) = (0, 1)
divide(1, 3) = (0, 1)
Последний остаток равен 1. Коэффициент:
0*3/3 + 0*9/3 + 64*81/3 + 1512*6561/3 + 23*43046721/3 = 333333333
и мы выполнили только 23 + 1512 + 64 = 1599 вычитаний вместо 333 333 333 вычитаний официального решения. Вот код:
def divide(num, div):
divs, sqs, sum = [div], [1], 0
while divs[-1] * divs[-1] < num:
divs.append(divs[-1] * divs[-1])
sqs.append(sqs[-1] * sqs[-1] * div)
while divs:
div, sq = divs.pop(), sqs.pop()
quot = 0
while div <= num:
quot += 1
num -= div
sum += (quot * sq)
return sum, num
Первый while
вычисляет и суммирует квадраты, а также каждый из квадратов, разделенных на div , поэтому в конечном коде деления нет. После первых while
стеки divs и sqs выглядят так:
divs = [3, 9, 81, 6561, 43046721]
sqs = [1, 3, 27, 2187, 14348907]
Второй while
многократно извлекает два стека, выполняет наивный алгоритм деления на повторные вычитания в третьем while
и накапливает сумму . Это намного быстрее, чем официальное решение, и не намного сложнее.
Вы можете запустить программу на https://ideone.com/CgVT1i.