对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
但是要使用 莫比乌斯反演, 于是回去学习…
年过后… 莫比乌斯反演学会了.
click here
这里不再赘述 .
#include<cstdio>
#include<algorithm>
#define reg register
const int maxn = 50005;
int prime_num;
int mu[maxn];
int mu_sum[maxn];
int prime[maxn];
bool is_prime[maxn];
void sieve(){
prime_num = 0, mu[1] = 1;
for(reg int i = 2; i < maxn; i ++){
if(!is_prime[i]) prime[++ prime_num] = i, mu[i] = -1;
for(reg int j = 1; j <= prime_num && i*prime[j] < maxn; j ++){
int t = i*prime[j];
is_prime[t] = 1;
if(i%prime[j] == 0){ mu[t] = 0; break ; }
mu[t] = -mu[i];
}
}
for(reg int i = 1; i < maxn; i ++) mu_sum[i] = mu_sum[i-1] + mu[i];
}
int Calc(int n, int m){
int lim = std::min(n, m), s = 0;
for(reg int l = 1, r; l <= lim; l = r+1){
r = std::min(n/(n/l), m/(m/l));
s += (mu_sum[r] - mu_sum[l-1]) * (n/l) * (m/l);
}
return s;
}
void Work(){
int a, b, c, d, k;
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
int Ans = Calc(b/k, d/k) - Calc((a-1)/k, d/k) - Calc(b/k, (c-1)/k) + Calc((a-1)/k, (c-1)/k);
printf("%d
", Ans);
}
int main(){
sieve();
int T;
scanf("%d", &T);
while(T --) Work();
return 0;
}