题目链接–传送门
题意:快速求出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); } }