1. 程式人生 > >bzoj 2301 Problem b - 莫比烏斯反演

bzoj 2301 Problem b - 莫比烏斯反演

flag class memory sample sin swa scrip return lag

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 - 莫比烏斯反演