Codeforces 955C Sad powers(數論)
阿新 • • 發佈:2018-11-17
題意
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<<"\n" #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\n",count(r)-count(l-1)); } return 0; }