题目链接–传送门
题意:快速求出L~R中的次幂数个数。 例如 16 = 24 , 16就算一个.
因为数据很大1018 所以我们只需暴力1~1016的次幂大于等于3的即可并且分开偶数次幂,偶数次幂可全当2次幂就行2次幂的数量自己思考一下很简单,最后在区间二分一下有几个数字就行, 二次幂的也可以。
ac代码:
#include <cstdio>
#include <string>
#include <iostream>
#include <map>
#include <cmath>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iterator>
using namespace std;
typedef long long ll;
const ll inf = 1e18;
const ll inn = 1e6;
const ll inx = 1e9;
const ll mx = 1e7+7;
ll tot;
ll su[mx];
ll po(ll a, ll b) {
ll st = 1;
while (b){
if (b&1)
st *= a;
a *= a;
b>>=1;
}
return st;
}
void init() {
tot = 0;
for (ll i = 1; i <= inn; ++i) {
ll sq = sqrt((double)i);
if(i == sq*sq) continue;
for (ll j = 3; po(i, j-2) <= inf/(i*i); j+=2) {
su[tot++] = po(i, j);
}
}
sort(su, su+tot);
tot = unique(su, su+tot)-su;
}
ll su2(ll a) {
ll l = 1, r = inx, ans = inx+1;
while (l <= r) {
ll mid = (l+r)>>1;
if (mid*mid >= a) {
ans = mid;
r = mid-1;
}
else l = mid+1;
}
return ans;
}
ll su3(ll a) {
ll l = 0, r = tot-1, ans = tot;
while (l <= r) {
ll mid = (l+r)>>1;
if (su[mid] >= a) {
ans = mid;
r = mid-1;
}
else l = mid+1;
}
return ans;
}
int main() {
int q;
ll l, r;
init();
scanf("%d", &q);
while (q--) {
scanf("%lld%lld", &l, &r);
ll sl2 = su2(l), sr2 = su2(r), sum;
if (sr2*sr2 == r) sr2++;
sum = sr2-sl2;
sl2 = su3(l), sr2 = su3(r);
if (su[sr2] == r) sr2++;
sum += sr2-sl2;
printf("%lld\n", sum);
}
}