We can program Euler's recursion for the sum of divisors, too. It only 
makes sense, when we need to compute the sum of divisors for many integers 
in 1:n, because then we can reuse the already computed values. It is the 
case, when we search for amicable numbers: we compute the vector of 
divisor-sums only once, and then search in that vector.

Euler's algorithm is remarkable, because it does not use any 
multiplications or divisions as coded below, only additions/subtractions 
and indexing. (Except the computation of the constant k, but that can be 
approximated with shift operations - not done in the code, or use n in 
place of 2k).

The auxiliary memory use is proportional to sqrt(n), which is small 
compared to the result vector of size n. The running time is O(n^1.5), 
which may or may not be competitive with the method in the previous post: 
the sum of divisors is computed for each input by factoring and compute a 
product over the prime factors.
~~~
function allDivSums(n) # returns an Int32 vector, v[i] = sum of divisors of 
i, i <= n
    k = iceil((sqrt(1+24n)+1)/6)
    pn = zeros(Int32,2k)
    pn[1:2:2k] = cumsum([1+3(0:k-1)])
    pn[2:2:2k] = cumsum([2+3(0:k-1)])
    sg = ones(Int32,2k)
    sg[3:4:2k] = sg[4:4:2k] = -1
    
    DS = ones(Int32,n)
    for u = 2:n
        s = 0; i = 1
        while i <= 2k && pn[i] < u
            s += flipsign(DS[u-pn[i]],sg[i])
            i += 1
        end
        if i <= 2k && pn[i] == u
            s += flipsign(u,sg[i])
        end
        DS[u] = s
    end
    return DS
end
~~~

Reply via email to