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 |
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:
- 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. - 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:
C++
#include<bits/stdc++.h>
using namespace std;
int mod = 1000000007;
int linearSum( int n)
{
return (n * (n + 1) / 2) % mod;
}
int rangeSum( int b, int a)
{
return (linearSum(b) -
linearSum(a)) % mod;
}
int totalSum( int n)
{
int result = 0;
int i = 1;
while ( true )
{
result += rangeSum(n / i, n / (i + 1)) *
(i % mod) % mod;
result %= mod;
if (i == n)
break ;
i = n / (n / (i + 1));
}
return result;
}
int main()
{
int N = 4;
cout << totalSum(N) << endl;
N = 12;
cout << totalSum(N) << endl;
return 0;
}
|
Java
class GFG{
static final int mod = 1000000007 ;
public static int linearSum( int n)
{
return (n * (n + 1 ) / 2 ) % mod;
}
public static int rangeSum( int b, int a)
{
return (linearSum(b) -
linearSum(a)) % mod;
}
public static int totalSum( int n)
{
int result = 0 ;
int i = 1 ;
while ( true )
{
result += rangeSum(n / i,
n / (i + 1 )) *
(i % mod) % mod;
result %= mod;
if (i == n)
break ;
i = n / (n / (i + 1 ));
}
return result;
}
public static void main(String[] args)
{
int N = 4 ;
System.out.println(totalSum(N));
N = 12 ;
System.out.println(totalSum(N));
}
}
|
Python3
mod = 1000000007
def linearSum(n):
return n * (n + 1 ) / / 2 % mod
def rangeSum(b, a):
return (linearSum(b) - (
linearSum(a))) % mod
def totalSum(n):
result = 0
i = 1
while True :
result + = rangeSum(
n / / i, n / / (i + 1 )) * (
i % mod) % mod;
result % = mod;
if i = = n:
break
i = n / / (n / / (i + 1 ))
return result
N = 4
print (totalSum(N))
N = 12
print (totalSum(N))
|
C#
using System;
class GFG{
static readonly int mod = 1000000007;
public static int linearSum( int n)
{
return (n * (n + 1) / 2) % mod;
}
public static int rangeSum( int b, int a)
{
return (linearSum(b) -
linearSum(a)) % mod;
}
public static int totalSum( int n)
{
int result = 0;
int i = 1;
while ( true )
{
result += rangeSum(n / i,
n / (i + 1)) *
(i % mod) % mod;
result %= mod;
if (i == n)
break ;
i = n / (n / (i + 1));
}
return result;
}
public static void Main(String[] args)
{
int N = 4;
Console.WriteLine(totalSum(N));
N = 12;
Console.WriteLine(totalSum(N));
}
}
|
Javascript
<script>
let mod = 1000000007;
function linearSum(n)
{
return (n * (n + 1) / 2) % mod;
}
function rangeSum(b, a)
{
return (linearSum(b) -
linearSum(a)) % mod;
}
function totalSum(n)
{
let result = 0;
let i = 1;
while ( true )
{
result += rangeSum(Math.floor(n / i),
Math.floor(n / (i + 1))) *
(i % mod) % mod;
result %= mod;
if (i == n)
break ;
i = Math.floor(n / (n / (i + 1)));
}
return result;
}
let N = 4;
document.write(totalSum(N) + "<br/>" );
N = 12;
document.write(totalSum(N));
</script>
|
Time complexity: O(?n)