caioj1281 GCD2

题目链接

题目大意为给你一个数 $n$ ,求所有 $1 \leq x, y \leq n $ 且 $\gcd(x, y)$ 为质数的 $(x, y)$ 数对个数。

题目没给数据范围,MLE + RE 了好多次终于弄清楚了数据范围大概在一千万左右。

这题有些卡空间,要注意数组不要开太多。


首先我们需要一个线性筛,来筛出 $1 - n$ 以内所有的数是否为质数,记为 $p[i]$,即若 $i$ 为质数则 $p[i] = 1$,否则为 $0$。

然后我们枚举最大公约数。

即设
$$ f(k) = \sum_{1 \leq x, y \leq n}[\gcd(x, y) = 1] $$

所求即

$$ \sum_{k = 1}^np[k]f(\lfloor\frac nk\rfloor) $$

分块求就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <cstdio>
#define MAXN 10000001

int notPrime[MAXN];
int prime[MAXN], mu[MAXN];

inline void Shaker(int n) {
int cnt = 0;
notPrime[0] = notPrime[1] = 1, mu[1] = 1;
for(int i = 2; i <= n; i++) {
if(!notPrime[i]) prime[cnt++] = i, mu[i] = -1;
for(int j = 0; j < cnt && prime[j] * i <= n; j++) {
notPrime[prime[j] * i] = 1;
if(i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
}

inline void SetSum(int n) {
for(int i = 1; i <= n; i++)
notPrime[i] = notPrime[i - 1] + !notPrime[i],
mu[i] = mu[i - 1] + mu[i];
}

inline long long f(long long x) {
long long res = 0;
for(long long l = 1; l <= x; l++) {
long long r = x / (x / l);
res = res + (mu[r] - mu[l - 1]) * (x / l) * (x / l);
l = r;
}
return res;
}

inline long long Get(int x) {
long long res = 0;
for(long long l = 1; l <= x; l++) {
long long r = x / (x / l);
res = res + (notPrime[r] - notPrime[l - 1]) * f(x / l);
l = r;
}
return res;
}

int main(int argc, char *argv[]) {
int n;
scanf("%d", &n);
Shaker(n), SetSum(n);
printf("%lld", Get(n));
return 0;
}