首页 > 代码库 > bzoj 2301 Problem b - 莫比乌斯反演

bzoj 2301 Problem b - 莫比乌斯反演

<style></style>

Description

对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

 

Input

第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k

 

Output

共n行,每行一个整数表示满足要求的数对(x,y)的个数

 

Sample Input

2
2 5 1 5 1
1 5 1 5 2

Sample Output


14
3

HINT

100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000


  题目大意 (如此简洁的题目就不需要我的烂文笔了)

  这是在迎接codeforces div 2一场蓝(灰)之前恭迎的最后的一道水题(一个名为Doggu的数论神犇这么说的)。好了,废话不多说了。

  如果你还没有做过bzoj 1101,那你应该赶紧做一下咯。

  推理和它一毛一样,然后你发现它求的实际上等于一个二维前缀和,于是它便真地成了一道水题了(你基本上不用改动什么,copy过来,二维前缀和加加减减就水掉了)。

Code

  1 /**  2  * bzoj  3  * Problem#2301  4  * Accepted  5  * Time:14640ms  6  * Memory:1576k  7  */  8 #include <iostream>  9 #include <cstdio> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #include <cstring> 14 #include <cstdlib> 15 #include <fstream> 16 #include <sstream> 17 #include <algorithm> 18 #include <map> 19 #include <set> 20 #include <stack> 21 #include <queue> 22 #include <vector> 23 #include <list> 24 #ifndef WIN32 25 #define Auto "%lld" 26 #else 27 #define Auto "%I64d" 28 #endif 29 using namespace std; 30 typedef bool boolean; 31 const signed int inf = (signed)((1u << 31) - 1); 32 const signed long long llf = (signed long long)((1ull << 61) - 1); 33 const double eps = 1e-6; 34 const int binary_limit = 128; 35 #define smin(a, b) a = min(a, b) 36 #define smax(a, b) a = max(a, b) 37 #define max3(a, b, c) max(a, max(b, c)) 38 #define min3(a, b, c) min(a, min(b, c)) 39 template<typename T> 40 inline boolean readInteger(T& u){ 41     char x; 42     int aFlag = 1; 43     while(!isdigit((x = getchar())) && x != - && x != -1); 44     if(x == -1) { 45         ungetc(x, stdin);     46         return false; 47     } 48     if(x == -){ 49         x = getchar(); 50         aFlag = -1; 51     } 52     for(u = x - 0; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - 0); 53     ungetc(x, stdin); 54     u *= aFlag; 55     return true; 56 } 57  58 const int limit = 5e4; 59  60 int n; 61 int num = 0; 62 int prime[10000]; 63 int miu[limit + 1]; 64 boolean vis[limit + 1]; 65  66 inline void Euler() { 67     memset(vis, false, sizeof(vis)); 68     miu[0] = 0, miu[1] = 1; 69     for(int i = 2; i <= limit; i++) { 70         if(!vis[i])    miu[i] = -1, prime[num++] = i; 71         for(int j = 0; j < num && prime[j] * 1LL * i <= limit; j++) { 72             int c = prime[j] * i; 73             vis[c] = true; 74             if((i % prime[j]) == 0) { 75                 miu[c] = 0; 76                 break; 77             } else { 78                 miu[c] = -1 * miu[i]; 79             } 80         } 81         miu[i] += miu[i - 1]; 82     } 83 } 84  85 inline void init() { 86     readInteger(n); 87 } 88  89 inline long long calc(int a, int b, int d) { 90     long long ret = 0; 91     a /= d, b /= d; 92     if(a == 0 || b == 0)    return 0; 93     if(a > b)    swap(a, b); 94     ret = 0; 95     for(int i = 1, j; i <= a; i = j + 1) { 96         j = min(a / (a / i), b / (b / i)); 97         ret += (a / j) * 1LL * (b / j) * (miu[j] - miu[i - 1]); 98     } 99     return ret;100 }101 102 inline void solve() {103     int a, b, c, d, e;104     while(n--) {105         scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);106         printf(Auto"\n", calc(b, d, e) - calc(a - 1, d, e) - calc(c - 1, b, e) + calc(a - 1, c - 1, e));107     }108 }109 110 int main() {111     Euler();112     init();113     solve();114     return 0;115 }

 

bzoj 2301 Problem b - 莫比乌斯反演