# 洛谷 P2522 [HAOI2011]Problem b

## 题意

$$n$$组询问，每次给出$$a,b,c,d,k$$，求$$\sum\limits_{x=a}^{b}\sum\limits_{y=c}^{d}[\gcd(x,y)=k]$$

## 思路

$$f(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j= 1}^{m}[\gcd(i,j)=k]$$

1. 容易得出原式等价于

$\sum\limits_{i = 1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j = 1}^{\lfloor\frac{m}{k}\rfloor}[\gcd(i,j) = 1]$

1. 因为$$\epsilon(n) =\sum\limits_{d|n}\mu(d)=[n=1]$$，由此可将原式化为

$\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum\limits_{d|gcd(i,j)}\mu(d)$

1. 改变枚举对象并改变枚举顺序，先枚举$$d$$，得

$\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}[d|i]\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}[d|j]$

1. 易得$$1\sim \lfloor\frac{n}{k}\rfloor$$中一共有$$\lfloor\frac{n}{dk}\rfloor$$$$d$$的倍数，同理$$1\sim \lfloor\frac{m}{k}\rfloor$$中一共有$$\lfloor\frac{m}{dk}\rfloor$$$$d$$的倍数，于是原式化为

$\sum\limits_{d=1}\mu(d)\lfloor\frac{n}{dk}\rfloor\lfloor\frac{m}{dk}\rfloor$

## 代码

/*
Author:loceaner
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int A = 1e6 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

char c = getchar(); int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}

int n, a, b, c, d, k, cnt, p[A], mu[A], sum[A];
bool vis[A];

void getmu() {
int MAX = 50010;
mu[1] = 1;
for (int i = 2; i <= MAX; i++) {
if (!vis[i]) mu[i] = -1, p[++cnt] = i;
for (int j = 1; j <= cnt && i * p[j] <= MAX; j++) {
vis[i * p[j]] = true;
if (i % p[j] == 0) break;
mu[i * p[j]] -= mu[i];
}
}
for (int i = 1; i <= MAX; i++) sum[i] = sum[i - 1] + mu[i];
}

int work(int x, int y) {
int ans = 0ll;
int max = min(x, y);
for (int l = 1, r; l <= max; l = r + 1) {
r = min(x / (x / l), y / (y / l));
ans += (1ll * x / (l * k)) * (1ll * y / (l * k)) * 1ll * (sum[r] - sum[l - 1]);
}
return ans;
}

void solve() {