Numbers within a range that can be expressed as power of two numbers


The problem statement includes printing the count of numbers within a range given that can be expressed as power of two numbers i.e. numbers which are perfect powers.

The numbers which are known as perfect powers is the number which can be expressed as $\mathrm{x^{y}}$,where x>0 and y>1 for all integers. For example, 8 is a perfect power because it can be expressed as $\mathrm{2^{3}}$,which is equal to 8 hence it is considered as a perfect power.

In this problem, we will be given a range as two positive integers in the input i.e. a and b and our task is to print the number of perfect powers that exist within the range [a,b].

Let’s understand the problem better with the below examples.

Input

a=1 , b=10

Output

4

Explanation − The range has been given in the input i.e. [1,10]. We need to find out the number of perfect powers in the range.

$\mathrm{1=1^{2}}$, hence it is a perfect power as it can be represented in the form of $\mathrm{x^{y}}$, where x>0 and y>1.

$\mathrm{4=2^{2}}$,here also x>0 and y>1.

$\mathrm{8=2^{3}}$

$\mathrm{9=3^{2}}$

Hence, there only exist 4 perfect powers within the range [1,10[. Therefore, 4 is the output.

Input

a=5 , b=20

Output

3

Explanation − The input given is [5,20]. The number of perfect powers in the given range are:

$\mathrm{8=2^{3}}$, since it can be represented as $\mathrm{x^{y}}$ where x>0 and y>1.

$\mathrm{9=3^{2}}$

$\mathrm{16=4^{2}}$

Since there exist only 3 perfect powers in the given range, therefore 3 is the required output.

Let’s understand the algorithm to find out the number of perfect powers in the given range.

Algorithm

We know that a perfect power is a number that can be expressed as $\mathrm{x^{y}}$,where x>0 and y>1. Since the largest value of long long data type in C++ is $\mathrm{10^{18}}$, the number of perfect squares exist are up to $\mathrm{10^{9}}$ because numbers greater than that will cause overflow in long long data types.

Calculating Perfect Squares within the range

For numbers which can be represented in $\mathrm{x^{y}}$, where y =2 i.e. the perfect squares in the given range can be calculated using the difference of square root of the given range.

If the given range is a and b ([a,b]), the number of perfect squares in the range can be calculated using the below formula:

Number of perfect squares in the range= floor(sqrtl(b)) − floor(sqrtl(a−1))

The floor(x) function returns the greatest integer less than or equal to the passed number in the function.

sqrtl() is used to get the square root of the passed number in a long double data type.

We can get the total number of perfect squares in the range [a,b] by using the above formula. We take sqrtl(a−1) just to include the a if it is also a perfect square.

Calculating Perfect Powers within the range

Now for the numbers of the form $\mathrm{x^{y}}$, where y>=3 and x>0 we will just generate the numbers with odd powers because even powers are included in the perfect squares.

The range of generating the odd powers will be up to $\mathrm{10^{6}}$ because the cube of the number will be the maximum value we can store in a long long data type.

  • So we will initialise a for loop from i=2 to $\mathrm{i<10^{6}+1}$ to store all the numbers which can be expressed in the form of $\mathrm{x^{y}}$ where y is an odd number. We will initialise a vector to store all the numbers with power greater than or equal to 3 and is an odd power for each value of x from 2 to $\mathrm{10^{6}}$

  • We will also initialise two sets to store the perfect squares and the second one to store the powers other than perfect squares.

  • Iterating in a for loop from i=2 to $\mathrm{10^{6}+1}$ and storing the squares of i for each value in the set. If the value of i already exists in the set we will continue iteration for the next value of i since i is a perfect square. Any perfect square raised to any power is also a perfect square of some number. So we will not calculate the other powers of i if i already exists in the set which means it is a perfect square.

  • If the value of i doesn’t exist in the set which depicts that i is not a perfect square. So we will calculate the odd powers of the number by iterating in a while loop. We will store the value of i in a variable, say a and check if i*i <= 1e18/a. We will keep storing the value of a*i*i in the set and update the value of a with a*i*i and further store all the values of the odd powers of i until it is less than the maximum value of long long data type by using the above condition in the while loop.

Once we are done with the iteration we will store all the values stored in the set in the vector we created. We used set first to store the values as it stores unique numbers in it and it also stores the numbers sorted.

Now since we have all the numbers which are perfect powers we will simply use binary search to find the number of perfect powers in the range.

We will store the number of perfect squares using the formula floor(sqrtl(b)) − floor(sqrtl(a−1)) in a variable in the given range [a,b]. Now we will use lower_bound() and upper_bound() functions in c++ to find the number of perfect powers in the given range and add them in the variable which will be our required output.

The lower_bound() function returns the iterator in the vector at the first number which is not less than the number passed in the function.

Similarly, the upper_bound() function returns the iterator in the vector at the first number greater than the number passed in the range.

If the value is not in the given vector, it returns the end iterator.

We will pass the lower range a in the lower_bound() function for the vector to get the iterator at the first number which is not less than the number. And the upper range b in the upper_bound() function to get the iterator at the first number greater than b. The difference of two will give the number of perfect powers in the given range.

Adding the number of perfect powers and perfect squares in the given range [a,b] will give the total numbers in the range which can be expressed in the power of two numbers.

We will use the algorithm in our approach in order to solve the problem.

Approach

The steps to follow to implement the above algorithm in our approach in order to find the total number which can be expressed in the power of two numbers in the range:

  • To precompute all the perfect powers till 1e18, we will write a function.

  • In the function we will store all the perfect powers till 1e18 in the vector using sets.

  • Now we will initialise a variable in which we add the total number of perfect squares in the given range using the formula floor(sqrtl(b)) − floor(sqrtl(a−1)). The difference between the square root of the numbers will give the total number whose squares lie in the given range.

  • Using the lower_bound() and upper_bound() function, we can get the iterator at the first number not less than the number and the first number greater than the number respectively. The difference of these will give us the perfect powers in the given range.

  • Adding the number of perfect squares in the perfect powers will give the total numbers in the range which can be expressed as the power of two numbers which will be our required output.

Example

//C++ code to find the total numbers in the range [a,b] which can be expressed as power of two numbers
#include <bits/stdc++.h>

using namespace std;

 long long int n=1000001; //to compute odd powers of numbers until n
 long long int maximum=1e18; //to ensure numbers don't exceed maximum value

set<long long int> sqr; //to store perfect squares
set<long long int> x; //to store odd powers of the number
vector<long long int> p; //to store the values stored in set x

//function to pre calculate all the perfect powers other than perfect squares till 1e18
void PowerCalculation()
{
   
    
    for(long long int i=2;i<n;i++)
    {
        
      long long int t=i*i;
      sqr.insert(t); //store the  square of i in the set
      
      if(sqr.find(i) !=sqr.end()) //if i is a perfect square, we will continue the loop
      {
          continue;
      }
      
      long long int val=i; //store i in val if it is not a perfect square
      while(i*i<=maximum/val) //check if i*i is less than or equal to maximum/val to update the next odd power of i in the set
      {
        val=val*i*i; //update val with the next odd power of i
        x.insert(val); //insert the value in the set
      }
      
    }
    
    for(auto i:x) //push all the values in the set of perfect powers in the vector
    {
     p.push_back(i); 
    
    }
}

//function to calculate the total numbers in the range which can be expressed as x^y
long long int perfectPower(long long int start,long long int end)
{
    //to store the number of perfect squares in the range
   long long  int Squares=(floor(sqrtl(end)))-floor((sqrtl(start-1)));
    
    //to find the index of the first number greater than end
   long long int endPoint = (upper_bound(p.begin(),p.end(), end) - p.begin());
    
    //to find the first number not less than start
    long long int startPoint = (lower_bound(p.begin(),p.end(), start) - p.begin());
    
    //adding number of perfect squares and perfect power in the number will give the ans
    long long int ans=Squares+(endPoint-startPoint);
    
    return ans;
}
int main()
{
    //calling the function to pre calculate odd powers of the number
    PowerCalculation();
    
   long int start=1;
    long int end=1000000;
   long long int ans=perfectPower(start,end);
   
   cout<<"The number of Perfect Power is : "<<ans<<endl;

    return 0;
}

Output

The number of Perfect Power is : 1111

Conclusion

The problem of finding the total numbers in the range which can be expressed in the power of two integers was discussed in the article. We precomputed all the perfect powers which allows us to find the total numbers in the range which are perfect powers in $\mathrm{O(logN)}$ runtime in C++.

I hope you understand the concept and the approach to solve the problem better after reading this article.

Updated on: 28-Aug-2023

93 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements