# 题意

$\sum_{i=a}^b\sum_{j=c}^d[gcd(i, j) = k]$

# 题解

$calc(\alpha, \beta) = \sum_{i=1}^{\alpha}\sum_{j=1}^{\beta}[gcd(i, j) = k]$

$A = \{ (x, y) | x < a\}$, $B = \{(x, y)|y < c\}$

$|S| = |U| - |A| - |B| + |A \cap B|$

$calc(b, d) - calc(a-1 ,d) - calc(b, c-1) + calc(a-1, c-1)$

$f(x) = \sum_{i=1}^b\sum_{j=1}^d[gcd(i, j) = x]$

$F(x) = \sum_{i=1}^b\sum_{j=1}^d[gcd(i, j) = \lambda， x|\lambda]$

$F(x) = \sum_{x|d} f(d)$

F(x)就相对好计算的多，我们很容易有：

$F(x) =\lfloor \frac{b}{i}\rfloor \lfloor\frac{d}{i} \rfloor$

1.$x|i$
2.$x|j$

$x \leq \lambda$

$f(x) =\sum_{d|x} \mu(d) F(\frac{x}{d})$

$f(x) = \sum_{x|d} \mu(\frac{d}{x}) F(d) = \sum_{x|d}\mu(\frac{d}{x}) \lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor$

$\lfloor \frac{n}{d} \rfloor$的取值最多有$2 \sqrt n$种（约数的个数），所以如果我们枚举$\lfloor \frac{n/m}{d} \rfloor$的取值，只需要枚举$2(\sqrt n + \sqrt m)$即可，复杂度就成了$\Theta (\sqrt n + \sqrt m)$

# 代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50005;
int T, a, b, c, d, k;
int mu[maxn+5], sumu[maxn+5], prime[maxn+5], check[maxn+5];
int tot = 0;
void get_mu() {
memset(check, 0, sizeof(check));
mu[1] = 1;
for(int i = 2; i <= maxn; i++) {
if(!check[i]) {
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++) {
if(i * prime[j] > maxn) break;
check[i * prime[j]] = 1;
if(i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
}

void init() {
get_mu();
for(int i = 1; i <= maxn; i++) sumu[i] = sumu[i-1] + mu[i];
}

int calc(int n, int m) {
n/=k;
m/=k;
int ret = 0;
int last;
if(n > m) swap(n, m);
for(int i = 1; i <= n; i = last + 1) {
last = min(n / (n/i), m / (m/i));
ret += (n / i) * (m / i) * (sumu[last] - sumu[i-1]);
}
return ret;
}
int main() {
init();
scanf("%d", &T);
while(T--) {
scanf("%d %d %d %d %d", &a, &b, &c, &d, &k);
int ans = calc(b, d) - calc(a-1, d) - calc(b, c-1) + calc(a-1, c-1);
printf("%d\n", ans);
}
return 0;
}


posted on 2017-02-03 18:15  蒟蒻konjac  阅读(90)  评论(0编辑  收藏

• 随笔 - 168
• 文章 - 0
• 评论 - 33