Perfect Power (1, 4, 8, 9, 16, 25, 27, …)


A Perfect Power is a Natural Number that is the product of equal natural factors. It can also be defined as an integer that can be expressed as a square power or a higher power of another integer greater than one.

For example, 4 can be expressed as the product of 2*2.

27 can be expressed as the product of 3*3*3. Hence, 4 and 27 are perfect powers.

Problem Statement

Given a number n, find the count of perfect numbers which are less than or equal to n.

Example 1

Input = 14
Output = 3

Explanation

1 = 1*1.
4 = 2*2.
9 = 3*3.

Hence, 1, 4, and 9 are the perfect powers less than 14.

Example 2

Input = 27
Output = 7

Explanation

1 = 1*1.
4 = 2*2.
9 = 3*3.
16 = 4*4.
25 = 5*5.
27 = 3*3*3.

Hence, 1, 4, 9, 16, 25, and 27 are the perfect powers less than equal to 27.

Approach 1: Brute force Approach

This approach involves calculating all the integral powers of integers from 1 to the square root of n. That means for each base having a value from 1 to the square root of n, we will calculate a number with base squared, base cubed, base quadrupled, and so on.

Pseudocode

Start
For  1<= i <=sqrt(n)
   j = i^2
   While j <= n:
      j = j*i
      Increase count
End

Example

Below is a C++ Program to count the perfect power numbers of type xy where x>0 and y>1, which are less than n.

#include <bits/stdc++.h>
using namespace std;

// Function to find all perfect power numbers less than n
int perfectPower(int n){
   // answer is going to store all power numbers
   // creating a set to store the unique values
   
   set<int> answer;
   answer.insert(1);
   
   // Iterating for base number i, from 2 to square root of n
   for (long long i = 2; i * i <= n; i++) {
      // starting from i squared
      long long j = i * i;
      answer.insert(j);
      
      // Increasing the power of base till its <= n
      while (j * i <= n) {
         // going to next power of i
         answer.insert(j * i);     
         j = j * i;
      }
   }
   // returning the size of set as it has no duplicates
   return answer.size();
}

// Driver Code
int main(){
   int n = 50;
   cout<< "Number of perfect powers less than or equal to 50:" << endl;
   cout << perfectPower(n);
   return 0;
}

Output

Number of perfect powers less than or equal to 50:
10

The time complexity of inserting in a set is O(log n), and there can be maximum n insertions.

Hence, the time Complexity is O(n log n)

The maximum size of the set can be n. Hence, the Space complexity is O(n)

Approach 2

In the last approach, we calculated all the powers of base starting from 2 to square root of n.

In this approach, we will separate the odd powers from even powers and calculate their numbers separately.

For calculating all the even powers less than and equal to n, we only need the square root of n. Because, the count of even powers smaller than n is equal to the square root of n.

Proof

Even powers smaller than and equal to 25 = 1, 4, 9, 16, 25, are 5 integers.

9 = 1, 4 , 9

For calculating odd powers: we will use the function used in the above approach.

We will find all the possible powers for bases greater than 2, and less than cube root of n.

And then, count the values which are odd. This can be checked as if the value is of even power, it will have an integral square root.

Also, instead of using sets, another option is to use vectors, but the vector will need to be sorted and remove any duplicates that get pushed into the vector.

Pseudocode

Start
For  1<= i <=cube root(n)
   J = i^2
   While j <= n:
      J = j*i
      If j is not a perfect square
      Increase count
end

Example

Below is a C++ Program to count number of perfect power numbers of type xy where x>0 and y>1 which are less than or equal to n.

#include <bits/stdc++.h>
using namespace std;

// Function to find all perfect power numbers less than n
int perfectPower(int n){
   
   // answer is going to store all power numbers
   vector<int> answer;
   
   // Iterating for base number i, from 2 to cube root of n
   for (long long i = 2; i * i * i <= n; i++) {
      // starting from i square
      long long j = i * i;
      
      // increase the power of j till it is <= n
      while (j * i <= n) {   
         j *= i;
         
         // only adding those values of j which
         // don't have a integral square root
         long long s = sqrt(j);
         if (s * s != j)
         answer.push_back(j);
      }
   }
   
   // sorting the vector and removing all the duplicate values
   sort(answer.begin(), answer.end());
   answer.erase(unique(answer.begin(), answer.end()), answer.end());
   
   // Num of even powers is equal to the square root of n.
   int numOfEven = (long long)sqrt(n);
   
   // Returning number of odd and even powers
   return answer.size() + numOfEven ;
}
int main(){
   
   // Function call
   cout<< "Number of perfect powers less than or equal to 10:" << endl;
   int ans = perfectPower(10);
   
   // Printing the answer
   cout << ans;
   return 0;
}

Output

Number of perfect powers less than or equal to 10:
4

Time complexity will be dominated by sorting the vector that is O(n log n)

Time Complexity: O(n log n)

Space Complexity: O(n^(1/4)) . Since we are only storing the odd powers less than n

Conclusion

In this tutorial, we solved the problem of counting the perfect powers less than or equal to a given number n.

We discussed 2 approaches −

  • Find all the possible powers up to the square root of n.

  • Split the solution in two parts and use the fact that the count of even powers smaller than n is square root of n. And, calculate the odd powers manually to save time and give a space optimized solution.

Updated on: 10-Mar-2023

701 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements