1. 程式人生 > >Codeforces 955C - Sad powers(數論 + 二分)

Codeforces 955C - Sad powers(數論 + 二分)

bound turn sta ons 所有 long long family 預處理 gin

鏈接:

http://codeforces.com/problemset/problem/955/C

題意:

Q次詢問(1≤Q≤1e5),每次詢問給出兩個整數L, R(1≤L≤R≤1e18),求所有符合條件的整數x的個數。
條件為:L≤x≤R,x = a的p次方(a, p為整數且a>0, p>1)。

分析:

一、當指數p=3時,底數a最多有1e6個,由於指數增加時底數收斂得很快,
所以我們可以將p>=3時的所有x放進vector裏排序去重(預處理),求x的個數的時候二分查找即可。
二、對於p=2,也可以使用二分查找來得到x的個數。
這兩種情況會有重復的x,所以要在預處理的時候把所有的平方數去掉。

代碼:

 1 #include <cstdio>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 typedef long long int LLI;
 7 const LLI UP = 1e18;
 8 vector<LLI> V;
 9 
10 LLI root(LLI n) { // 二分查找n的平方根r(n <= r*r)
11     LLI L = 1, R = 1e9 + 1;
12     while(L < R) {
13 LLI M = L + (R - L) / 2; 14 if(M * M >= n) R = M; 15 else L = M + 1; 16 } 17 return L; 18 } 19 20 void constant() { 21 vector<LLI> V2 = {1}; 22 int u = 1e6; 23 for(int n = 2; n <= u; n++) { 24 for(LLI i = 1LL * n * n * n; ; i *= n) {
25 V2.push_back(i); 26 if(i > UP / n) break; // 防止 long long 溢出 27 } 28 } 29 sort(V2.begin(), V2.end()); 30 V2.erase(unique(V2.begin(), V2.end()), V2.end()); 31 for(int i = 0; i < V2.size(); i++) { 32 LLI r = root(V2[i]); 33 if(r * r != V2[i]) V.push_back(V2[i]); 34 } 35 } 36 37 int main() { 38 constant(); // 預處理 39 int q; 40 LLI L, R; 41 scanf("%d", &q); 42 while(q--) { 43 scanf("%I64d%I64d", &L, &R); 44 LLI ans = upper_bound(V.begin(), V.end(), R) 45 - lower_bound(V.begin(), V.end(), L); 46 ans += root(R+1) - root(L); 47 printf("%I64d\n", ans); 48 } 49 return 0; 50 }

Codeforces 955C - Sad powers(數論 + 二分)