Ответ 1
Да. Вы можете аннулировать цикл for и найти сумму в постоянное время.
В соответствии с Принцип включения-исключения суммируя кратные x
и кратные y
и вычитая общий множественный ( s), которые были добавлены дважды, должны предоставить нам требуемую сумму.
Required Sum = sum of ( multiples of x that are <= N ) +
sum of ( multiples of y that are <= N ) -
sum of ( multiples of (x*y) that are <= N )
Пример:
N = 15
x = 3
y = 4
Required sum = ( 3 + 6 + 9 + 12 + 15) + // multiples of 3
( 4 + 8 + 12 ) - // multiples of 4
( 12 ) // multiples of 12
Как видно выше, нам пришлось вычитать 12
, поскольку он добавлен дважды, потому что он является общим кратным.
Как весь алгоритм O (1)?
Пусть sum(x, N)
представляет собой сумму кратных x
, которые меньше или равны N
.
sum(x,N) = x + 2x + ... + floor(N/x) * x
= x * ( 1 + 2 + ... + floor(N/x) )
= x * ( 1 + 2 + ... + k) // Where k = floor(N/x)
= x * k * (k+1) / 2 // Sum of first k natural num = k*(k+1)/2
Теперь k = floor(N/x)
может быть вычислен в постоянное время.
Как только k
известен sum(x,N)
, может быть вычислен в постоянное время.
Таким образом, требуемая сумма также может быть вычислена в постоянное время.
EDIT:
Вышеупомянутое обсуждение справедливо только тогда, когда x
и y
являются сопутствующими параметрами. Если нет, нам нужно использовать LCM(x,y)
вместо x*y
. Существует много способов найти LCM, один из которых состоит в том, чтобы разделить продукт на GCD. Теперь GCD невозможно вычислить в постоянное время, но его временная сложность может быть значительно меньше линейного.