2301: [HAOI2011]Problem b
Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 6435 Solved: 2986
[Submit][Status][Discuss]
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
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
Source
【题解】
很巧的容斥。
给的询问a,b,c,d很难搞,考虑容斥!
有点像二维前缀和,即考虑x = 1...a/b,y = 1...c/d,答案为solve(b,d) - solve(b,c-1) - solve(a-1,d) + solve(a-1,c-10
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #define min(a, b) ((a) < (b) ? (a) : (b)) 9 #define max(a, b) ((a) > (b) ? (a) : (b)) 10 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 11 inline void swap(long long &a, long long &b) 12 { 13 long long tmp = a;a = b;b = tmp; 14 } 15 inline void read(long long &x) 16 { 17 x = 0;char ch = getchar(), c = ch; 18 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 19 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 20 if(c == '-') x = -x; 21 } 22 23 const long long INF = 0x3f3f3f3f; 24 const long long MAXN = 100000; 25 26 long long miu[MAXN], bp[MAXN], p[MAXN], tot; 27 void make_miu() 28 { 29 miu[1] = 1; 30 for(register long long i = 2;i <= MAXN;++ i) 31 { 32 if(!bp[i]) p[++tot] = i, miu[i] = -1; 33 for(register long long j = 1;j <= tot && i * p[j] <= MAXN;++ j) 34 { 35 bp[i * p[j]] = 1; 36 if(i % p[j] == 0) 37 { 38 miu[i * p[j]] = 0; 39 break; 40 } 41 miu[i * p[j]] = -miu[i]; 42 } 43 } 44 for(register long long i = 1;i <= MAXN;++ i) miu[i] += miu[i - 1]; 45 } 46 47 long long a,b,c,d,k; 48 49 long long solve(long long n, long long m) 50 { 51 n/=k, m/=k; 52 if(n == 0 || m == 0) return 0; 53 long long tmp = min(n, m); 54 long long ans = 0, last; 55 for(register long long i = 1;i <= tmp;i = last + 1) 56 { 57 last = min(n/(n/i), m/(m/i)); 58 ans += (miu[last] - miu[i - 1]) * (n/i) * (m/i); 59 } 60 return ans; 61 } 62 63 long long n; 64 65 int main() 66 { 67 make_miu(); 68 read(n); 69 for(;n;-- n) 70 { 71 read(a), read(b), read(c), read(d), read(k); 72 printf("%lld ", solve(b,d) - solve(a - 1,d) - solve(b,c - 1) + solve(a - 1,c - 1)); 73 } 74 return 0; 75 }