📌  相关文章
📜  可以表示为两个数字的幂的范围内的数字

📅  最后修改于: 2021-04-23 20:22:39             🧑  作者: Mango

给定两个整数L和R。在给定范围[L,R]中找到理想功效的数量。如果存在一个整数a> 0,p> 1使得x = a p ,那么数字x被认为是完美的幂。

例子 :

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.

先决条件:检查数字是否可以表示为x ^ y,二进制搜索和完美幂(1、4、8、9、16、25、27等)

方法:让我们修复一些功率p。显而易见,x的总数不超过10 18 / p ,因此对于特定的p x p不会超过10 18 。同时,仅当p = 2时,该数量相对较大;对于所有其他p≥3,此类数量的总和将为10 6数量级。在[1,10 18 ]范围内有10 9个正方形,因此无法存储它们来回答我们的查询。

要么生成p≥2的所有幂,然后处理其中的所有完美平方,要么仅生成数字的奇数幂,如3、5、7等。然后,查询(L,R)的答案等于生成的数量L和R之间的数字加上范围内的一些完美平方。

  1. 范围内的完美平方数是R的平方根的底值与(L – 1)的平方根的底值之差,即( floor(sqrt(R))– floor(sqrt(L – 1)) )。请注意,由于精度问题,标准sqrt可能会产生不正确的值,因此请使用二进制搜索或cmath中定义的sqrtl内置函数(有关sqrtl的更多说明,请参见此处)。
  2. 产生数字的那些奇数幂。首先,进行算术运算,找到可以表示为最大10 18的数的幂的数字,这样我们可以回答许多查询,而无需为每个查询一次又一次地处理它们。首先从2到10 6循环循环(因为我们正在计算幂p≥3,而10 6是幂上升到3的最大数不能超过10 18 ),对于每个值,我们将其平方插入集合并检查此外,如果该值已经是一个理想平方(已经存在于集合中),则我们找不到该数的其他幂(因为理想平方的任何幂也是理想平方)。否则,请运行内部循环以查找数字的奇数幂,直到其超过10 18并插入另一个集合中,例如“ s”。通过这种方法,我们没有在集合“ s”中施加任何完美的平方。

因此,最终答案将是范围内的完美平方数的总和以及R的上限值和L的下限值的差(使用二进制搜索)。
下面是上述方法在C++中的实现。

// CPP Program to count the numbers
// within a range such that number
// can be expressed as power of some
// other number
#include 
  
using namespace std;
  
#define N 1000005
#define MAX 1e18
  
// Vector to store powers greater than 3
vector powers;
  
// set to store perfect squares
set squares;
  
// set to store powers other
// than perfect squares
set 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;
}
输出:
Number of powers between 12 and 29 = 3
Number of powers between 1 and 100000000000 = 320990