# 解析

$F(k)=\sum_{x=1}^{\big\lfloor\frac{n}{k}\big\rfloor}f(k\cdot x)$

$\displaystyle F(k)=\Big\lfloor\frac{n}{k}\Big\rfloor\Big\lfloor\frac{m}{k}\Big\rfloor$

$f(k)=\sum_{x=1}^{\big\lfloor\frac{n}{k}\big\rfloor}\bigg(\mu(x)\cdot F(k\cdot x)\bigg)=\sum_{x=1}^{\big\lfloor\frac{n}{k}\big\rfloor}\bigg(\mu(x)\Big\lfloor\frac{n}{kx}\Big\rfloor\Big\lfloor\frac{m}{kx}\Big\rfloor\bigg)$

• 当 $1\leqslant d < \sqrt{n}$ 时，由于 $d$ 只有 $\sqrt{n}$ 个，所以 $\displaystyle \Big\lfloor\frac{n}{d}\Big\rfloor$ 也至多有 $\sqrt{n}$ 个取值。
• 当 $\sqrt{n}\leqslant d\leqslant n$ 时，由于 $\displaystyle \Big\lfloor\frac{n}{d}\Big\rfloor$ 只有 $\sqrt{n}$ 个，所以 $\displaystyle \Big\lfloor\frac{n}{d}\Big\rfloor$ 也只有至多 $\sqrt{n}$ 个取值。
• 故 $\displaystyle \Big\lfloor\frac{n}{d}\Big\rfloor$ 至多有 $O(\sqrt{n})$ 个取值。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 50010;
int T, tot, prime[maxn], mu[maxn], sum[maxn];

void sieve() {
fill(prime, prime + maxn, 1);
mu[1] = 1, tot = 0;
for (int i = 2; i < maxn; i++) {
if (prime[i]) {
prime[++tot] = i, mu[i] = -1;
}
for (int j = 1; j <= tot && i * prime[j] < maxn; j++) {
prime[i * prime[j]] = 0;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
for (int i = 1; i < maxn; i++) {
sum[i] = sum[i - 1] + mu[i];
}
}

int calc(int n, int m, int k) {
if (n > m) swap(n, m);
int ans = 0;
n /= k, m /= k;
for (int i = 1, nxt = 1; i <= n; i = nxt + 1) {
nxt = min(n / (n / i), m / (m / i));
ans += (sum[nxt] - sum[i - 1]) * (n / i) * (m / i);
}
return ans;
}

int main() {
sieve();
scanf("%d", &T);
while (T--) {
int a, b, c, d, k;
scanf("%d %d %d %d %d", &a, &b, &c, &d, &k);
printf("%d\n", calc(b, d, k) - calc(b, c - 1, k) - calc(a - 1, d, k) + calc(a - 1, c - 1, k));
}
return 0;
}

posted @ 2018-10-06 21:40  AlessandroChen  阅读(101)  评论(0编辑  收藏  举报