You're given Q queries of the form (L, R).
For each query you have to find the number of such x that L ≤ x ≤ R and there exist integer numbers a > 0, p > 1 such that x = ap.
Input
The first line contains the number of queries Q (1 ≤ Q ≤ 105).
The next Q lines contains two integers L, R each (1 ≤ L ≤ R ≤ 1018).
Output
Output Q lines — the answers to the queries.
Example
Input
6 1 4 9 9 5 7 12 29 137 591 1 1000000
Output
2 1 0 3 17 1111
Note
In query one the suitable numbers are 1 and 4.
题意:
给定一个区间[l,r],问区间内有多少个数x满足x=a^q,并且a>0&&q>1
题解:
问存在多少个x满足x=a^q,如果数据小的话可以直接把a^q出现的数字用map容器存储起来,排个序输出就行了。
不过,这道题的l和r的范围是1e19,没办法对所有范围的数据都暴力存储起来,不过我们可以对部分进行这样的操作。
当q=2的时候,a的范围是1e9,单独分析:
毋庸置疑,x^2在x轴上是单调的,那么我们就可以使用二分的方法判断在[l,r]区间范围内有多少个x^2。
右边界:r,左边界:l-1
通过右边界对应的数我们找到一个x,通过左边界对应的数我们找到一个数y,那么x-y就是指数为2的数量。
当q>2的时候,a的范围小于等于1e6,可以暴力:
将所有的情况使用map容器存起来,然后用sort进行一个排序,接下来使用upper_bound函数找到l和r中间有多少个数成立。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
vector<ll>number;
map<ll,int>mapp;
bool sqrtt(ll x)
{
ll y=sqrt(x);
if(y*y==x||(y+1)*(y+1)==x||(y-1)*(y-1)==x)
return true;
return false;
}
void init()
{
number.push_back(1);
for(ll i=2;i<=1e6;++i)
{
for(ll j=i*i*i;j<=1e18;j*=i)
{
if(!mapp[j]&&!sqrtt(j))
{
//去重复的数字和平方数字
mapp[j]=1;
number.push_back(j);
}
if(1e18/i<j) break;
}
}
sort(number.begin(),number.end());
}
ll value(ll x)
{
ll l=1,r=1e9;
ll mid,ans=0;
while(l<=r)
{
mid=(l+r)/2;
if(mid*mid<=x)
{
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
return ans;
}
ll solve(ll l,ll r)
{
return value(r)-value(l-1);
}
int main()
{
ll T,l,r;
init();
cin>>T;
while(T--)
{
scanf("%I64d%I64d",&l,&r);
ll ans=0;
ans+=upper_bound(number.begin(),number.end(),r)-upper_bound(number.begin(),number.end(),l-1);
ans+=solve(l,r);
if(l==1) ans-=1;
printf("%I64d\n",ans);
}
return 0;
}