2301: [HAOI2011]Problem b ( 分块+莫比乌斯反演+容斥)
2301: [HAOI2011]Problem b
Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 6015 Solved: 2741
[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
/* * @Author: LyuC * @Date: 2017-10-08 16:54:59 * @Last Modified by: LyuC * @Last Modified time: 2017-10-08 21:06:44 */ /* 直接处理会超时,对于6/6=1 6/5=1 6/4=1这样的实际和已合并同类项一次 计算出来,能节约不少时间 */ #include <bits/stdc++.h> #define LL long long #define MAXN 50005 using namespace std; int t; int a, b, c, d, k; int sum [ MAXN ]; bool check[MAXN]; int mu[MAXN]; int prime[MAXN]; void mobi(){ memset(check,false,sizeof check); mu[1]=1; int tol=0; for(int i=2;i<MAXN;i++){ if(!check[i]){ prime[tol++]=i; mu[i]=-1; } for(int j=0;j<tol;j++){ if(i*prime[j]>MAXN) break; check[i*prime[j]]=true; if(i%prime[j]==0){ mu[i*prime[j]]=0; break; }else{ mu[i*prime[j]]=-mu[i]; } } } } inline int Count (int a, int b) { int s=0; if (a > b) { swap (a, b); } for (int i = 1, last = 0; i <= a; i = last + 1) { last = min( a / (a / i), b / (b / i) ); s += (sum [ last ] - sum [ i - 1 ]) * (a / i) * (b / i); } return s; } inline void init () { sum [ 0 ] = 0; for (int i = 1;i < MAXN; i ++) { sum [ i ] = sum[ i - 1 ] + mu [ i ]; } } int main () { // freopen ("in.txt", "r", stdin); mobi (); init (); scanf ("%d", &t); while (t -- ) { scanf ("%d%d%d%d%d", &a, &b, &c, &d, &k); int res = Count ( b / k, d / k ) - Count ( ( a - 1 ) / k, d / k ) - Count ( b / k, (c - 1) / k ) + Count ( ( a - 1 ) / k, ( c -1 ) / k ); printf ( "%d\n", res ); } return 0; }
我每天都在努力,只是想证明我是认真的活着.