# [Luogu P2522] [BZOJ 2301] [HAOI2011]Problem b

### 输入输出格式

#### 输出格式：

$n$行，每行一个整数表示满足要求的数对$(x,y)$的个数

### 输入输出样例

#### 输入样例#1：

2
2 5 1 5 1
1 5 1 5 2


#### 输出样例#1：

14
3


### 说明

100%的数据满足：$1≤n≤50000，1≤a≤b≤50000，1≤c≤d≤50000，1≤k≤50000$

### 解题分析

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

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
#define MX 50050
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (;  isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
int pcnt;
int miu[MX], pri[MX];
bool npr[MX];
void get_miu()
{
R int i, j, tar;
miu[1] = 1;
for (i = 2; i <= 50000; ++i)
{
if (!npr[i]) pri[++pcnt] = i, miu[i] = -1;
for (j = 1; j <= pcnt; ++j)
{
tar = i * pri[j];
if (tar > 50000) break;
npr[tar] = true;
if (!(i % pri[j])) {miu[tar] = 0; break;}
miu[tar] = -miu[i];
}
}
for (R int i = 1; i <= 50000; ++i) miu[i] += miu[i - 1];
}
IN ll calc(R int up1, R int up2, R int k)
{
if (up1 > up2) std::swap(up1, up2);
int bd = up1 / k, bd2 = up2 / k;
R int lef = 1, rig;
ll ret = 0;
W (lef <= bd)
{
rig = std::min(bd / (bd / lef), bd2 / (bd2 / lef));
ret += 1ll *(miu[rig] - miu[lef - 1]) * (bd / lef) * (bd2 / lef);
lef = rig + 1;
}
return ret;
}
int main()
{
int T, a, b, c, d, k;
in(T); get_miu();
W (T--)
{
in(a), in(b), in(c), in(d), in(k);
ll ans = calc(b, d, k) - calc(a - 1, d, k) - calc(b, c - 1, k) + calc(a - 1, c - 1, k);
printf("%lld\n", ans);
}
}


©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客