Given a positive integer n, the task is to find the value of Σi F(i) where i is from 1 to n and function F(i) is defined as the sum of all divisors of i.
Examples:
Input: n = 4
Output: 15
Explanation:
F(1) = 1
F(2) = 1 + 2 = 3
F(3) = 1 + 3 = 4
F(4) = 1 + 2 + 4 = 7
So, F(1) + F(2) + F(3) + F(4) = 1 + 3 + 4 + 7 = 15.
Input: n = 5
Output: 21
Explanation:
F(1) = 1
F(2) = 1 + 2 = 3
F(3) = 1 + 3 = 4
F(4) = 1 + 2 + 4 = 7
F(5) = 1 + 5 = 6
So, F(1) + F(2) + F(3) + F(4) + F(5) = 1 + 3 + 4 + 7 + 6 = 21.
Input: n = 1
Output: 1
Explanation:
F(1) = 1
So, F(1) = 1.
Table of Content
[Naive Approach] Check Divisors for Every Number - O(n ^ 2) Time and O(1) Space
The idea is to calculate the sum of divisors for every number from
1tonindividually. For each numberi, we check all numbers from1toiand add those that dividei. The divisor sums obtained for all numbers are then accumulated to get the final answer.
#include <iostream>
using namespace std;
long long sumOfDivisors(int n)
{
long long ans = 0;
// Find sum of divisors for every number
for (int i = 1; i <= n; i++)
{
long long currSum = 0;
// Find divisors of i
for (int j = 1; j <= i; j++)
{
if (i % j == 0)
{
currSum += j;
}
}
ans += currSum;
}
return ans;
}
int main()
{
int n = 5;
cout << sumOfDivisors(n);
return 0;
}
public class GFG {
public static long sumOfDivisors(long n)
{
long ans = 0;
// Find sum of divisors for every number
for (long i = 1; i <= n; i++) {
long currSum = 0;
// Find divisors of i
for (long j = 1; j <= i; j++) {
if (i % j == 0) {
currSum += j;
}
}
ans += currSum;
}
return ans;
}
public static void main(String[] args)
{
long n = 5;
long ans = sumOfDivisors(n);
System.out.println(ans);
}
}
def sumOfDivisors(n):
ans = 0
# Find sum of divisors for every number
for i in range(1, n + 1):
currSum = 0
# Find divisors of i
for j in range(1, i + 1):
if i % j == 0:
currSum += j
ans += currSum
return ans
if __name__ == "__main__":
n = 5
print(sumOfDivisors(n))
using System;
public class GFG {
public static long sumOfDivisors(int n)
{
long ans = 0;
// Find sum of divisors for every number
for (int i = 1; i <= n; i++) {
long currSum = 0;
// Find divisors of i
for (int j = 1; j <= i; j++) {
if (i % j == 0) {
currSum += j;
}
}
ans += currSum;
}
return ans;
}
public static void Main()
{
int n = 5;
long ans = sumOfDivisors(n);
Console.WriteLine(ans);
}
}
function sumOfDivisors(n) {
let ans = 0;
// Find sum of divisors for every number
for (let i = 1; i <= n; i++) {
let currSum = 0;
// Find divisors of i
for (let j = 1; j <= i; j++) {
if (i % j === 0) {
currSum += j;
}
}
ans += currSum;
}
return ans;
}
// Driver code
let n = 5;
console.log(sumOfDivisors(n));
Output
21
[Expected Approach] Contribution of Divisors - O(n) Time and O(1) Space
The idea is to count the contribution of each divisor instead of finding divisors for every number. A number
iappears as a divisor in all its multiples up ton, i.e., [n / i]times. Therefore, its total contribution isi × [n / i]. Summing the contributions of all numbers from1tongives the required answer.
Summing the contributions of all numbers from 1 to n gives the required answer:
Let us understand with example:
Input: n = 5
- Initially, ans = 0.
- For i = 1, contribution = 1 × (5 / 1) = 5, so ans = 5.
- For i = 2, contribution = 2 × (5 / 2) = 4, so ans = 9.
- For i = 3, contribution = 3 × (5 / 3) = 3, so ans = 12.
- For i = 4 and i = 5, contributions are 4 and 5 respectively, so ans = 21.
Therefore, the final answer is 21.
#include <bits/stdc++.h>
using namespace std;
long long sumOfDivisors(long long n)
{
long long ans = 0;
// Calculate contribution of every divisor
for (long long i = 1; i <= n; i++)
{
ans += i * (n / i);
}
return ans;
}
int main()
{
long long n = 5;
cout << sumOfDivisors(n);
return 0;
}
public class GFG {
public static long sumOfDivisors(long n)
{
long ans = 0;
// Calculate contribution of every divisor
for (long i = 1; i <= n; i++) {
ans += i * (n / i);
}
return ans;
}
public static void main(String[] args)
{
long n = 5;
System.out.println(sumOfDivisors(n));
}
}
def sumOfDivisors(n):
ans = 0
# Calculate contribution of every divisor
for i in range(1, n + 1):
ans += i * (n // i)
return ans
# Driver code
if __name__ == "__main__":
n = 5
print(sumOfDivisors(n))
using System;
public class GFG {
public static long sumOfDivisors(long n)
{
long ans = 0;
// Calculate contribution of every divisor
for (long i = 1; i <= n; i++) {
ans += i * (n / i);
}
return ans;
}
public static void Main()
{
long n = 5;
Console.WriteLine(sumOfDivisors(n));
}
}
function sumOfDivisors(n)
{
let ans = 0;
// Calculate contribution of every divisor
for (let i = 1; i <= n; i++)
{
ans += i * Math.floor(n / i);
}
return ans;
}
// Driver code
let n = 5;
console.log(sumOfDivisors(n));
Output
21
[Alternate Approach] Using Harmonic Lemma - O(√n) Time and O(1) Space
The idea is to use the Harmonic Lemma, which states that the sequence ⌊n/1⌋, ⌊n/2⌋, ..., ⌊n/n⌋ contains at most 2√n distinct values. Therefore, instead of processing every index individually, we group together all consecutive indices having the same quotient. For each group, we compute its contribution in one step and then jump directly to the next group.
Proof of Harmonic Lemma:
- Consider the sequence: floor(n/1), floor(n/2), ..., floor(n/n).
- Case 1: If floor(n/i) > √n, then i < √n. Since there are at most √n such indices, there can be at most √n distinct values.
- Case 2: If floor(n/i) ≤ √n, then the quotient can only be an integer from 1 to √n, so there are at most √n such distinct values.
- Therefore, the total number of distinct values is at most √n + √n = 2√n.
- Hence, the sequence contains at most 2√n distinct values, which is known as the Harmonic Lemma.
Using this result, we process all consecutive indices having the same value of floor(n / i) together. For the current index l, let k = n / l. The last index having the same quotient is r = n / k. We compute the contribution of the entire range [l, r] using the arithmetic progression formula and then continue from r + 1.
Let us understand with example:
Input: n = 5
Initially, ans = 0, l = 1
Iteration 1:
- k = 5 / 1 = 5
- r = 5 / 5 = 1
- Range = [1, 1]
- Contribution = 5 × (1) = 5
- ans = 5
- l = 2
Iteration 2:
- k = 5 / 2 = 2
- r = 5 / 2 = 2
- Range = [2, 2]
- Contribution = 2 × (2) = 4
- ans = 9
- l = 3
Iteration 3:
- k = 5 / 3 = 1
- r = 5 / 1 = 5
- Range = [3, 5]
- Contribution = 1 × (3 + 4 + 5) = 12
- ans = 21
- l = 6
Now l > n, so the loop terminates. Final Answer = 21.
#include <iostream>
using namespace std;
long long sumOfDivisors(int n)
{
long long ans = 0;
long long l = 1;
while (l <= n)
{
long long k = n / l;
// Last index having same value of (n / i)
long long r = n / k;
// Sum of numbers from l to r
long long rangeSum = (r * (r + 1)) / 2 - ((l - 1) * l) / 2;
ans += k * rangeSum;
l = r + 1;
}
return ans;
}
int main()
{
int n = 5;
cout << sumOfDivisors(n);
return 0;
}
public class GFG {
public static long sumOfDivisors(long n)
{
long ans = 0;
long l = 1;
while (l <= n) {
long k = n / l;
// Last index having same value of (n / i)
long r = n / k;
// Sum of numbers from l to r
long rangeSum
= (r * (r + 1)) / 2 - ((l - 1) * l) / 2;
ans += k * rangeSum;
l = r + 1;
}
return ans;
}
public static void main(String[] args)
{
long n = 5;
System.out.println(sumOfDivisors(n));
}
}
def sumOfDivisors(n):
ans = 0
l = 1
while l <= n:
k = n // l
# Last index having same value of (n / i)
r = n // k
# Sum of numbers from l to r
rangeSum = (r * (r + 1)) // 2 - ((l - 1) * l) // 2
ans += k * rangeSum
l = r + 1
return ans
if __name__ == "__main__":
n = 5
print(sumOfDivisors(n))
using System;
public class GFG {
public static long sumOfDivisors(int n)
{
long ans = 0;
long l = 1;
while (l <= n) {
long k = n / l;
// Last index having same value of (n / i)
long r = n / k;
// Sum of numbers from l to r
long rangeSum = (r * (r + 1)) / 2 - ((l - 1) * l) / 2;
ans += k * rangeSum;
l = r + 1;
}
return ans;
}
public static void Main()
{
int n = 5;
Console.WriteLine(sumOfDivisors(n));
}
}
function sumOfDivisors(n) {
let ans = 0;
let l = 1;
while (l <= n) {
let k = Math.floor(n / l);
// Last index having same value of (n / i)
let r = Math.floor(n / k);
// Sum of numbers from l to r
let rangeSum = (r * (r + 1)) / 2 - ((l - 1) * l) / 2;
ans += k * rangeSum;
l = r + 1;
}
return ans;
}
// Driver code
let n = 5;
console.log(sumOfDivisors(n));
Output
21