题意:问[L,R]的区间内有多少个数是幂p次(>=2)得来的数
思路:
1.暴力,处理出所有1,1e18内所有的幂次数,用upper_bound处理出落在区间[L,R]内的幂次数个数.
2.突然发现暴力不行,怎么整? 发现对于p=2的情况可以单独求解(根号有坑点啊),数量级到了1e9 . 而p>=3的数量级<=1e6 .
#include<bits/stdc++.h>
#define PI acos(-1.0)
using namespace std;
typedef long long ll;
const int N=1e5+50;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
vector <ll> vec;
map <ll,int> mp;
bool square(ll x){
ll t=sqrt(x);
if(t*t==x || (t+1)*(t+1)==x || (t-1)*(t-1)==x) return true;
return false;
}
void prepare(){
vec.push_back(1);
for(ll i=2;i<=1e6;++i){
for(ll t=i*i*i;t<=1e18;t*=i){
if(!mp[t] && !square(t)) mp[t]=1,vec.push_back(t); ///去重,去平方数
if(1ll*1e18/i<t) break;
}
}
sort(vec.begin(),vec.end());
}
ll f(ll x){
ll l=1,r=1e9;
ll ans=0;
while(l<=r){
ll mid=(l+r)/2;
if(mid*mid<=x) ans=mid,l=mid+1;
else r=mid-1;
}
// cout <<"~~"<<ans<<endl;
return ans;
}
int main(void){
prepare(); /// del 1e6 p>=3 cout <<"BUG"<<endl,
ll q,l,r;
cin >>q;
while(q--){
scanf("%I64d%I64d",&l,&r);
ll ans=0;
ans+= f(r)-f(l-1);//用二分求根号 || 判断是否平方数也可以
// cout <<"ans="<<ans<<endl;
ans+=upper_bound(vec.begin(),vec.end(),r)-upper_bound(vec.begin(),vec.end(),l-1);
if(l==1) ans--;
printf("%I64d\n",ans);
}
return 0;
}
/**************
**************/