C. Sad powers
time limit per test
2 secondsmemory limit per test
256 megabytesinput
standard inputoutput
standard outputYou'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
Copy
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.
这个题目有些难度,主要是压缩时间,需要对数据进行一些处理和分类,首先1e18没有超long long ,先固定指数p,x^p <= 1e18 可以推导出 x <= 10^(18/p) 。若 p = 2, 则有 10^9 个的数字满足条件,若 p >= 3, 则最多有 10^6 的数字满足条件。所以先预处理,把所有不是完全平方数且满足 x^p<=1e18(p>=3) 的x都加入到vector, 排序去重,对于每次查询输出 sqrt(R) - sqrt(L-1) + upper_bound(R) - lower_bound(L)。对于查询x的平方根,用二分查找。
总的时间复杂度为 (1e6 + Qlog1e18)。
#include<bits/stdc++.h> using namespace std; typedef long long ll; vector<ll>g; ll root(ll x) //二分查找平方根 { ll left = 0, right = 1e9; ll mid,ans; while (left<=right) { mid = (left+right)>>1; if (mid*mid<=x) { ans = mid; left = mid+1; } else right = mid-1; } return ans; } void init() //预处理p>=3的数 { g.clear(); for (ll i=2; i<=1e6; i++) { double t = 1.0*i*i*i; ll s = i*i*i; while (t<2e18) { ll root_s = root(s); if (root_s*root_s<s) g.push_back(s); t *= i; s *= i; } } sort(g.begin(),g.end()); int sz = unique(g.begin(),g.end())-g.begin(); } int main() { init(); int q; scanf("%d",&q); ll l,r; while (q--) { scanf("%I64d %I64d",&l,&r); int ans1 = upper_bound(g.begin(),g.end(),r) - lower_bound(g.begin(),g.end(),l); int ans2 = root(r) - root(l-1); printf("%d ",ans1+ans2); } return 0; }