题意
q组询问,每次询问给定L,R,求[L,R]区间内有多少个数可以写成ap的形式,其中a>0,p>1,1 ≤ L ≤ R ≤ 1e18。
思路
- 对于p>2的情况,由于随着指数p的增大,小于1e18的p次幂的数量会急剧减小,总数量的级别在1e6多左右,因此可预处理。L,R不超过1e18,可以直接枚举数字1-1e6,将每个数字不超过1e18的且不是平方数的p次幂推入数组中,排序去重。以便回答询问时可二分求数量。
- 对于p=2的情况,对上界直接开方,即可知道有多少个平方数。
做法不难,但容易看不清复杂度,以至于想不到做法。建议手写开方,否则误差较大。
代码
#include<bits/stdc++.h>
#define dd(x) cout<<#x<<" = "<<x<<" "
#define de(x) cout<<#x<<" = "<<x<<"
"
#define sz(x) int(x.size())
#define All(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef priority_queue<int> BQ;
typedef priority_queue<int,vector<int>,greater<int> > SQ;
const int maxn=1e5+10,mod=1e9+7,INF=0x3f3f3f3f;
ll Sqrt(ll x)
{
ll l=1,r=x,ans=0;
while (l<=r)
{
ll mid=(l+r)>>1;
ld mul=ld(mid)*mid;
if (mul<x)
l=mid+1,ans=mid;
else if (mul>x)
r=mid-1;
else
return mid;
}
return ans;
}
vector<ll> v;
vector<ll>:: iterator End;
void init()
{
for (ll i=2;i<=1e6;++i)
{
ll a=i*i*i;
ld _a=a;
while (_a<=1e18)
{
ll t=Sqrt(a);
if (t*t!=a)
v.pb(a);
a*=i;
_a*=i;
}
}
sort(All(v));
End=unique(All(v));
}
ll count(ll n)
{
ll p=upper_bound(v.begin(),End,n)-v.begin();
return Sqrt(n)+p;
}
int main()
{
init();
int n;
cin>>n;
while (n--)
{
ll l,r;
scanf("%lld%lld",&l,&r);
printf("%lld
",count(r)-count(l-1));
}
return 0;
}