Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

Given two integers L and R. Find the number of perfect powers in the given range [L, R]. A number x is said to be perfect power if there exists some integers a > 0, p > 1 such that x = ap. Examples :

Input : 1 4
Output : 2
Explanation : 
Suitable numbers are 1 and 4 where 1
can be expressed as 1 = 12 
and 4 can be expressed as 4 = 22

Input : 12 29
Output : 3
Explanation : 
Suitable numbers are 16, 25 and 27.

Prerequisites : Check if a number can be expressed as x^y, Binary Search and Perfect power (1, 4, 8, 9, 16, 25, 27, …) Approach : Let’s fix some power p. It’s obvious that there are no more than 1018/p numbers x such that xp doesn’t exceed 1018 for a particular p. At the same time, only for p = 2 this amount is relatively huge, for all other p ? 3 the total amount of such numbers will be of the order of 106. There are 109 squares in the range [1, 1018], so can’t store them to answer our query. Either, generate all of powers for p ? 2 and dispose of all perfect squares among them or generate only odd powers of numbers like 3, 5, 7, etc. Then answer to query (L, R) is equal to the amount of generated numbers between L and R plus some perfect squares in range.

  1. The number of perfect squares in the range is the difference of floor value of square root of R and floor value of square root of (L – 1), i.e. (floor(sqrt(R)) – floor(sqrt(L – 1)). Note that due to precision issues the standard sqrt might produce incorrect values, so either use binary search or sqrtl inbuilt function defined in cmath (Check here for more description of sqrtl).
  2. To generate those odd powers of numbers. First of all, do precomputation of finding such numbers that can be expressed as power of some number upto 1018 so that we can answer many queries and no need to process them again and again for each query. Start by iterating a loop from 2 to 106 (since we are calculating for powers p ? 3 and 106 is the maximum number whose power raised to 3 cannot exceed 1018), for each value we insert its square into a set and check further if that value is already a perfect square (already present in the set), we do not find any other powers of that number (since any power of a perfect square is also a perfect square). Otherwise, run an inside loop to find odd powers of the number until it exceeds 1018 and insert into another set say ‘s’. By this approach, we haven’t pushed any perfect square in the set ‘s’.

Hence the final answer would be sum of number of perfect squares in the range and difference of upper value of R and lower value of L (using binary search). Below is the implementation of above approach in C++. 

C++




// CPP Program to count the numbers
// within a range such that number
// can be expressed as power of some
// other number
#include <bits/stdc++.h>
 
using namespace std;
 
#define N 1000005
#define MAX 1e18
 
// Vector to store powers greater than 3
vector<long int> powers;
 
// set to store perfect squares
set<long int> squares;
 
// set to store powers other
// than perfect squares
set<long int> s;
 
void powersPrecomputation()
{
    for (long int i = 2; i < N; i++)
    {
        // pushing squares
        squares.insert(i * i);
 
        // if the values is already
        // a perfect square means
        // present in the set
        if (squares.find(i) != squares.end())
                continue;
 
        long int temp = i;
 
        // run loop until some
        // power of current number
        // doesn't exceed MAX
        while (i * i <= MAX / temp)
        {
            temp *= (i * i);
 
            /* pushing only odd powers
            as even power of a number
            can always be expressed as
            a perfect square which is
            already present in set squares */
            s.insert(temp);
        }
    }
 
    // Inserting those sorted
    // values of set into a vector
    for (auto x : s)
        powers.push_back(x);
}
 
long int calculateAnswer(long int L, long int R)
{
    // calculate perfect squares in
    // range using sqrtl function
    long int perfectSquares = floor(sqrtl(R)) -
                            floor(sqrtl(L - 1));
 
    // calculate upper value of R
    // in vector using binary search
    long int high = (upper_bound(powers.begin(),
            powers.end(), R) - powers.begin());
 
    // calculate lower value of L
    // in vector using binary search
    long int low = (lower_bound(powers.begin(),
            powers.end(), L) - powers.begin());
 
    // add into final answer
    perfectSquares += (high - low);
 
    return perfectSquares;
}
 
// Driver Code
int main()
{
    // precompute the powers
    powersPrecomputation();
 
    // left value of range
    long int L = 12;
     
    // right value of range
    long int R = 29;
 
    cout << "Number of powers between " << L
            << " and " << R << " = " <<
            calculateAnswer(L, R) << endl;
 
    L = 1;
    R = 100000000000;
 
    cout << "Number of powers between " << L
            << " and " << R << " = " <<
            calculateAnswer(L, R) << endl;
 
    return 0;
}


Java




// JAVA Program to count the numbers
// within a range such that number
// can be expressed as power of some
// other number
import java.util.*;
 
public class Main {
 
    static final int N = 1000005;
    static final double MAX = 1e18;
 
    // Vector to store powers greater than 3
    static ArrayList<Long> powers = new ArrayList<>();
 
    // set to store perfect squares
    static TreeSet<Long> squares = new TreeSet<>();
 
    // set to store powers other than perfect squares
    static TreeSet<Long> s = new TreeSet<>();
 
    public static void powersPrecomputation()
    {
        for (long i = 2; i < N; i++) {
            // pushing squares
            squares.add(i * i);
 
            // if the value is already a perfect square
            // means present in the set
            if (squares.contains(i))
                continue;
 
            long temp = i;
 
            // run loop until some power of current number
            // doesn't exceed MAX
            while (i * i <= MAX / temp) {
                temp *= (i * i);
 
                /* pushing only odd powers
                   as even power of a number can always be
                   expressed as a perfect square which is
                   already present in set squares */
                s.add(temp);
            }
        }
 
        // Inserting those sorted values of set into a
        // vector
        powers.addAll(s);
    }
 
    public static long calculateAnswer(long L, long R)
    {
        // calculate perfect squares in range using sqrt
        // function
        long perfectSquares
            = (long)(Math.floor(Math.sqrt(R))
                     - Math.floor(Math.sqrt(L - 1)));
 
        // calculate upper value of R in vector using binary
        // search
        int high = upperBound(powers, R);
 
        // calculate lower value of L in vector using binary
        // search
        int low = lowerBound(powers, L);
 
        // add into final answer
        perfectSquares += (high - low);
 
        return perfectSquares;
    }
 
    // Java equivalent of C++ upper_bound function
    public static int upperBound(ArrayList<Long> arr,
                                 long value)
    {
        int l = 0, r = arr.size();
        while (l < r) {
            int mid = l + (r - l) / 2;
            if (arr.get(mid) <= value) {
                l = mid + 1;
            }
            else {
                r = mid;
            }
        }
        return l;
    }
 
    // Java equivalent of C++ lower_bound function
    public static int lowerBound(ArrayList<Long> arr,
                                 long value)
    {
        int l = 0, r = arr.size();
        while (l < r) {
            int mid = l + (r - l) / 2;
            if (arr.get(mid) < value) {
                l = mid + 1;
            }
            else {
                r = mid;
            }
        }
        return l;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // precompute the powers
        powersPrecomputation();
 
        // left value of range
        long L = 12;
 
        // right value of range
        long R = 29;
 
        System.out.println("Number of powers between " + L
                           + " and " + R + " = "
                           + calculateAnswer(L, R));
 
        L = 1;
        R = 100000000000L;
 
        System.out.println("Number of powers between " + L
                           + " and " + R + " = "
                           + calculateAnswer(L, R));
    }
}


Python3




# Python Program to count the numbers
# within a range such that number
# can be expressed as power of some
# other number
 
import math
import bisect
 
N = 1000005
MAX = int(1e18)
 
# Vector to store powers greater than 3
powers = []
 
# set to store perfect squares
squares = set()
 
# set to store powers other
# than perfect squares
s = set()
 
 
def powersPrecomputation():
    for i in range(2, N):
        # pushing squares
        squares.add(i * i)
 
        # if the value is already
        # a perfect square means
        # present in the set
        if i in squares:
            continue
 
        temp = i
 
        # run loop until some
        # power of current number
        # doesn't exceed MAX
        while i * i <= MAX / temp:
            temp *= i * i
 
            # pushing only odd powers
            # as even power of a number
            # can always be expressed as
            # a perfect square which is
            # already present in set squares
            s.add(temp)
 
    # Inserting those sorted
    # values of set into a list
    for x in sorted(s):
        powers.append(x)
 
 
def calculateAnswer(L, R):
    # calculate perfect squares in
    # range using sqrt function
    perfectSquares = math.floor(math.sqrt(R)) - math.floor(math.sqrt(L - 1))
 
    # calculate upper value of R
    # in list using binary search
    high = len(powers) if R >= powers[-1] else bisect.bisect_right(powers, R)
 
    # calculate lower value of L
    # in list using binary search
    low = bisect.bisect_left(powers, L)
 
    # add into final answer
    perfectSquares += (high - low)
 
    return perfectSquares
 
 
# Driver Code
if __name__ == "__main__":
    # precompute the powers
    powersPrecomputation()
 
    # left value of range
    L = 12
 
    # right value of range
    R = 29
 
    print("Number of powers between", L,
          "and", R, "=", calculateAnswer(L, R))
 
    L = 1
    R = 100000000000
 
    print("Number of powers between", L,
          "and", R, "=", calculateAnswer(L, R))
 
  #  this code is contributed by rutikbhosale


C#




// C# Program to count the numbers
// within a range such that number
// can be expressed as power of some
// other number
 
using System;
using System.Collections.Generic;
using System.Linq;
 
class Program {
    const int N = 1000005;
    const double MAX = 1e18;
 
    static List<long> powers = new List<long>();
    static HashSet<long> squares = new HashSet<long>();
    static HashSet<long> s = new HashSet<long>();
 
    static void PowersPrecomputation()
    {
        // add 1 to squares
        squares.Add(1);
 
        for (long i = 2; i < N; i++) {
            // pushing squares
            squares.Add(i * i);
 
            // if the values is already
            // a perfect square means
            // present in the set
            if (squares.Contains(i))
                continue;
 
            long temp = i;
 
            // run loop until some
            // power of current number
            // doesn't exceed MAX
            while (i * i <= MAX / temp) {
                temp *= (i * i);
 
                /* pushing only odd powers
                as even power of a number
                can always be expressed as
                a perfect square which is
                already present in set squares */
                s.Add(temp);
            }
        }
 
        // Inserting those sorted
        // values of set into a list
        powers = s.ToList();
        powers.Sort();
 
        // add 1 to powers
        powers.Insert(0, 1);
    }
    static long CalculateAnswer(long L, long R)
    {
        // calculate perfect squares in
        // range using Math.Sqrt function
        long perfectSquares
            = (long)Math.Floor(Math.Sqrt(R))
              - (long)Math.Floor(Math.Sqrt(L - 1));
 
        // calculate upper value of R
        // in list using binary search
        long high = powers.BinarySearch(R);
        if (high < 0)
            high = ~high;
 
        // calculate lower value of L
        // in list using binary search
        long low = powers.BinarySearch(L);
        if (low < 0)
            low = ~low;
 
        // add into final answer
        perfectSquares += (high - low);
 
        return perfectSquares;
    }
 
    static void Main(string[] args)
    {
        // precompute the powers
        PowersPrecomputation();
 
        // left value of range
        long L = 12;
 
        // right value of range
        long R = 29;
 
        Console.WriteLine("Number of powers between " + L
                          + " and " + R + " = "
                          + CalculateAnswer(L, R));
 
        L = 1;
        R = 100000000000;
 
        Console.WriteLine("Number of powers between " + L
                          + " and " + R + " = "
                          + CalculateAnswer(L, R));
    }
}
 
// this code is contributed by rutikbhosale


Javascript




// JavaScript function to count the numbers
// within a range such that number
// can be expressed as power of some
// other number
const N = 1000005;
const MAX = 1e18;
 
// Array to store powers greater than 3
let powers = [];
 
// Set to store perfect squares
let squares = new Set();
 
// Set to store powers other
// than perfect squares
let s = new Set();
 
function powersPrecomputation() {
  for (let i = 2; i < N; i++) {
    // adding squares to set
    squares.add(i * i);
 
    // if the values is already
    // a perfect square means
    // present in the set
    if (squares.has(i)) continue;
 
    let temp = i;
 
    // run loop until some
    // power of current number
    // doesn't exceed MAX
    while (i * i <= MAX / temp) {
      temp *= i * i;
 
      /* adding only odd powers
      as even power of a number
      can always be expressed as
      a perfect square which is
      already present in set squares */
      s.add(temp);
    }
  }
 
  // Adding those values of set into an array
  for (let x of s) powers.push(x);
}
 
function calculateAnswer(L, R) {
  // calculate perfect squares in
  // range using Math.floor(Math.sqrt(R))
  let perfectSquares =
    Math.floor(Math.sqrt(R)) - Math.floor(Math.sqrt(L - 1));
 
  // calculate upper value of R
  // in array using binary search
  let high = powers.filter((p) => p <= R).length;
 
  // calculate lower value of L
  // in array using binary search
  let low = powers.filter((p) => p >= L).length;
 
  // add into final answer
  perfectSquares += high - low;
 
  return perfectSquares;
}
 
// Driver code
let L = 12;
let R = 29;
 
console.log(
  "Number of powers between " +
    L +
    " and " +
    R +
    " = " +
    calculateAnswer(L, R)
);
 
L = 1;
R = 100000000000;
 
console.log(
  "Number of powers between " +
    L +
    " and " +
    R +
    " = " +
    calculateAnswer(L, R)
);
// this code is contributed by devendra1


Output

Number of powers between 12 and 29 = 3
Number of powers between 1 and 100000000000 = 320990


Last Updated : 23 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads