Sum of all divisors from 1 to N | Set 2

Given a positive integer N, the task is to find the sum of divisors of first N natural numbers.

Examples:

Input: N = 4
Output: 15
Explanation:
Sum of divisors of 1 = (1)
Sum of divisors of 2 = (1+2)
Sum of divisors of 3 = (1+3)
Sum of divisors of 4 = (1+2+4)
Hence, total sum = 1 + (1+2) + (1+3) + (1+2+4) = 15

Input: N = 5
Output: 21
Explanation:
Sum of divisors of 1 = (1)
Sum of divisors of 2 = (1+2)
Sum of divisors of 3 = (1+3)
Sum of divisors of 4 = (1+2+4)
Sum of divisors of 5 = (1+5)
Hence, total sum = (1) + (1+2) + (1+3) + (1+2+4) + (1+5) = 21

For linear time approach, refer to Sum of all divisors from 1 to N



Approach:
To optimize the approach in the post mentioned above, we need to look for a solution with logarithmic complexity. A number D is added multiple times in the final answer. Let us try to observe a pattern of repetitive addition.
Considering N = 12:

D Number of times added
1 12
1 12
2 6
3 4
5, 6 2
7, 8, 9, 10, 11, 12 1

From the above pattern, observe that every number D is added (N / D) times. Also, there are multiple D that have same (N / D). Hence, we can conclude that for a given N, and a particular i, numbers from (N / (i + 1)) + 1 to (N / i) will be added i times.

Illustration:

  1. N = 12, i = 1
    (N/(i+1))+1 = 6+1 = 7 and (N/i) = 12
    All numbers will be 7, 8, 9, 10, 11, 12 and will be added 1 time only.
  2. N = 12, i = 2
    (N/(i+1))+1 = 4+1 = 5 and (N/i) = 6
    All numbers will be 5, 6 and will be added 2 times.

Now, assume A = (N / (i + 1)), B = (N / i)
Sum of numbers from A + 1 to B = Sum of numbers from 1 to B – Sum of numbers from 1 to A
Also, instead of just incrementing i each time by 1, find next i like this, i = N/(N/(i+1))

Below is the implementation of the above approach:

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python program for
# the above approach
  
mod = 1000000007
  
# Functions returns sum
# of numbers from 1 to n
def linearSum(n):
    return n*(n + 1)//2 % mod
  
# Functions returns sum
# of numbers from a+1 to b
def rangeSum(b, a):
    return (linearSum(b) - (
          linearSum(a))) % mod
  
# Function returns total
# sum of divisors
def totalSum(n):
  
    # Stores total sum
    result = 0
    i = 1
  
    # Finding numbers and
    # its occurence
    while True:
          
        # Sum of product of each
        # number and its occurence
        result += rangeSum(
            n//i, n//(i + 1)) * (
                  i % mod) % mod;
          
        result %= mod;
        if i == n:
            break
        i = n//(n//(i + 1))
          
    return result        
  
# Driver code
  
N= 4
print(totalSum(N))
  
N= 12
print(totalSum(N))

chevron_right


Output:

15
127

Time complexity: O(log N)

competitive-programming-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.