给定两个整数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之间的数字加上范围内的一些完美平方。
- 范围内的完美平方数是R的平方根的底值与(L – 1)的平方根的底值之差,即( floor(sqrt(R))– floor(sqrt(L – 1)) )。请注意,由于精度问题,标准sqrt可能会产生不正确的值,因此请使用二进制搜索或cmath中定义的sqrtl内置函数(有关sqrtl的更多说明,请参见此处)。
- 产生数字的那些奇数幂。首先,进行算术运算,找到可以表示为最大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