题目大意

即求

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

分析

容易想到,独立出函数 $f(k)$ 使得

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

利用 Mobius 反演化简,设 $F(d)$

$$ F(n) = \sum_{n \mid d} f(d) = \sum_{i=1}^x \sum_{j=1}^y [n \mid i][n \mid j] = \left\lfloor \frac{x}{n} \right\rfloor \left\lfloor \frac{y}{n} \right\rfloor $$

反演化简有

$$ f(n) = \sum_{n \mid d} \mu\left(\frac{d}{n}\right)F(d) = \sum_{t=1}^{\min(x,y)} \mu(t) \left\lfloor \frac{x}{tn} \right\rfloor \left\lfloor \frac{y}{tn} \right\rfloor $$

预处理出 $\mu(t)$ 的前缀和,剩下的就是一个二重分块了。

const ll MN = 50000;

bool notp[1000001];
int prime[200001], cnt, mu[MN];

void Mobius(int n); // 预处理 Mobius 函数

ll f(ll a, ll b) {
	ll mab = min(a, b);
	ll sum = 0;
	for (ll l = 1, r; l <= mab; l = r + 1) {
		r = min(a / (a / l), b / (b / l));
		sum += (mu[r] - mu[l - 1]) * (a / l) * (b / l);
	}
	return sum;
}

int main() {
	ll ttt = rr();
	Mobius(MN - 1);
	for (ll i = 1; i <= MN - 1; i++)
		mu[i] += mu[i - 1];
	for (ll i = 1; i <= ttt; i++) {
		ll a = rr(), b = rr(), c = rr(), d = rr();
		ll k = rr();
		a--, c--;
		a /= k, b /= k, c /= k, d /= k;
		ll ans = f(b, d) - f(a, d) - f(b, c) + f(a, c);
		printf("%lld\n", ans);
	}
	return 0;
}

类似题目

P2158 仪仗队:即 $k = 1$ 的特殊情况。

P3455 ZAP-Queries:几乎一样。

P2257 YY 的 GCD:比这题难,单独开篇。