Sum of all perfect square divisors of numbers from 1 to N

Given a number N, the task is to find the sum of all the perfect square divisors of numbers from 1 to N.

Examples:

Input: N = 5
Output: 9
Explanation: N = 5
Perfect square divisors of 1 = 1.
Similarly, perfect square divisors of 2, 3 = 1.
Perfect square divisors of 4 = 1, 4.
Perfect square divisors of 5 = 1 (of course for any prime only 1 will be the perfect square divisor)
So, total sum = 1+1+1+(1+4)+1 = 9.

Input: N = 30
Output: 126

Input: N = 100
Output: 910



Naive Approach: This approach is based on the approach implemented in this article
The above problem can be solved in O(N1/k) for any Kth power divisors, where N is the number up to which we have to find the sum. This is because, in this sum, every number will contribute floor(N/p) or int(N/p) times. Thus, while iterating through these perfect powers, we just need to add [p * int(N/p)] to the sum.

Time Complexity: O(√N)

Efficient Approach:

  • Let us start from start = 2, find the largest range (start to end) for which floor(N/(start2)) = floor(N/(end2))
  • The contribution of all perfect squares in the interval [start, end] will contribute floor(N/(start2)) times, hence we can do update for this range at once.
  • Contribution for range [start, end] can be given as:
  • floor(N/(start2))*(sumUpto(end) – sumUpto(start-1))

  • How to find range?
    For a given value of start, end can be found by
  • sqrt(N/K), where K = floor(N/(start^2))

  • Now the next range can be found by substituting start = end+1.

Time complexity: O(N1/3) as N/(x2) cannot take more than N1/3 different values for a fixed value of N.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to find the
// sum of all perfect square
// divisors of numbers from 1 to N
  
#include <bits/stdc++.h>
using namespace std;
  
#define MOD 1000000007
#define int unsigned long long
  
// Function for finding inverse
// of a number iteratively
// Here we will find the inverse
// of 6, since it appears as
// denominator in the formula of
// sum of squares from 1 to N
int inv(int a)
{
    int o = 1;
    for (int p = MOD - 2;
         p > 0; p >>= 1) {
  
        if ((p & 1) == 1)
            o = (o * a) % MOD;
        a = (a * a) % MOD;
    }
    return o;
}
  
// Store the value of the inverse
// of 6 once as we don't need to call
// the function again and again
int inv6 = inv(6);
  
// Formula for finding the sum
// of first n squares
int sumOfSquares(int n)
{
  
    n %= MOD;
    return (((n * (n + 1))
             % MOD * (2 * n + 1))
            % MOD * inv6)
           % MOD;
}
  
int sums(int n)
{
  
    // No perfect square
    // exists which is
    // less than 4
    if (n < 4)
        return 0;
  
    // Starting from 2, present value
    // of start is denoted here as
    // curStart
    int curStart = 2, ans = 0;
  
    int sqrtN = sqrt(n);
    while (curStart <= n / curStart) {
  
        int V = n / (curStart * curStart);
  
        // Finding end of the segment
        // for which the contribution
        // will be same
        int end = sqrt(n / V);
  
        // Using the above mentioned
        // formula to find ans % MOD
        ans += (n / (curStart * curStart)
                % MOD * (sumOfSquares(end)
                         + MOD
                         - sumOfSquares(curStart - 1)))
               % MOD;
  
        if (ans >= MOD)
            ans -= MOD;
  
        // Now for mthe next iteration
        // start will become end+1
        curStart = end + 1;
    }
  
    // Finally returning the answer
    return ans;
}
  
// Driver Code
int32_t main()
{
    int input[] = { 5 };
    for (auto x : input) {
        cout << "sum of all perfect"
             << " square divisors from"
             << " 1 to " << x
             << " is: ";
  
        // Here we are adding x
        // because we have not
        // counted 1 as perfect
        // squares so if u want to
        // add it you can just add
        // that number to the ans
        cout << x + sums(x) << endl;
    }
    return 0;
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to find the 
# sum of all perfect square 
# divisors of numbers from 1 to N 
from math import *
MOD = 1000000007
  
# Function for finding inverse 
# of a number iteratively 
# Here we will find the inverse 
# of 6, since it appears as 
# denominator in the formula of 
# sum of squares from 1 to N 
def inv (a):
  
    o = 1
    p = MOD - 2
    while (p > 0):
  
        if (p % 2 == 1):
            o = (o * a) % MOD
  
        a = (a * a) % MOD
        p >>= 1
  
    return
  
# Store the value of the inverse 
# of 6 once as we don't need to call 
# the function again and again 
inv6 = inv(6)
  
# Formula for finding the sum 
# of first n squares
def sumOfSquares (n):
  
    n %= MOD
    return (((n * (n + 1)) %
            MOD * (2 * n + 1)) % 
            MOD * inv6) % MOD
  
def sums (n):
  
    # No perfect square exists which
    # is less than 4
    if (n < 4):
        return 0
  
    # Starting from 2, present value
    # of start is denoted here as curStart
    curStart = 2
    ans = 0
  
    sqrtN = int(sqrt(n))
    while (curStart <= n // curStart):
        V = n // (curStart * curStart)
  
        # Finding end of the segment for 
        # which the contribution will be same
        end = int(sqrt(n // V))
  
        # Using the above mentioned
        # formula to find ans % MOD
        ans += ((n // (curStart * curStart) %
                MOD * (sumOfSquares(end) +
                MOD - sumOfSquares(curStart - 1))) % MOD)
  
        if (ans >= MOD):
            ans -= MOD
  
        # Now for mthe next iteration
        # start will become end+1
        curStart = end + 1
  
    # Finally return the answer
    return ans 
  
# Driver Code
if __name__ == '__main__':
  
    Input = [5]
    for x in Input:
        print("sum of all perfect "\
              "square " , end = '')
        print("divisors from 1 to", x,
              "is: ", end = '')
  
        # Here we are adding x because we have
        # not counted 1 as perfect squares so if u 
        # want to add it you can just add that 
        # number to the ans
        print(x + sums(x))
  
# This code is contributed by himanshu77

chevron_right


Output:

sum of all perfect square divisors from 1 to 5 is: 9


Time Complexity: O(N1/3)

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.



Improved By : himanshu77