GCD
题目描述
给定正整数 n n n,求 1 ≤ x , y ≤ n 1\le x,y\le n 1≤x,y≤n 且 gcd ( x , y ) \gcd(x,y) gcd(x,y) 为素数的数对 ( x , y ) (x,y) (x,y) 有多少对。
输入格式
只有一行一个整数,代表 n n n。
输出格式
一行一个整数表示答案。
样例 #1
样例输入 #1
4
样例输出 #1
4
提示
样例输入输出 1 解释
对于样例,满足条件的 ( x , y ) (x,y) (x,y) 为 ( 2 , 2 ) (2,2) (2,2), ( 2 , 4 ) (2,4) (2,4), ( 3 , 3 ) (3,3) (3,3), ( 4 , 2 ) (4,2) (4,2)。
数据规模与约定
- 对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 7 1\le n\le10^7 1≤n≤107。
来源:bzoj2818。
本题数据为洛谷自造数据,使用 CYaRon 耗时 5 5 5 分钟完成数据制作。
Solve:
// 正解貌似是欧拉函数,不过mobius反演也可以做。。。
题目所求式子为
∑
i
=
1
n
∑
j
=
1
n
[
g
c
d
(
i
,
j
)
∈
P
r
i
m
e
]
,首先对该式子进行一定的化简变形。
原式
=
∑
p
∈
P
r
i
m
e
∑
i
=
1
n
∑
j
=
1
n
[
g
c
d
(
i
,
j
)
=
p
]
=
∑
p
∈
P
r
i
m
e
∑
i
=
1
⌊
n
p
⌋
∑
j
=
1
⌊
n
p
⌋
[
g
c
d
(
i
,
j
)
=
1
]
化简到这里感觉有些希望,下面先进行莫比乌斯反演的套路变换
=
∑
p
∈
P
r
i
m
e
∑
i
=
1
⌊
n
p
⌋
∑
j
=
1
⌊
n
p
⌋
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
=
∑
p
∈
P
r
i
m
e
∑
d
=
1
⌊
n
p
⌋
μ
(
d
)
⌊
n
p
d
⌋
2
至此时间复杂度降至
O
(
n
1.5
log
n
)
,还是过不去
.
.
.
这里式子还可以继续化简,属于一个常见的继续化简的技巧
令
T
=
p
d
,我们转而枚举
T
=
∑
T
=
1
n
⌊
n
T
⌋
2
∑
p
∣
T
,
p
∈
P
r
i
m
e
μ
(
T
p
)
令
f
(
T
)
=
∑
p
∣
T
,
p
∈
P
r
i
m
e
μ
(
T
p
)
观察
f
(
T
)
的性质,发现
T
∈
P
r
i
m
e
时,
f
(
T
)
=
1
接着我们观察一下
f
(
p
∗
T
)
的性质
,
其中
p
∈
P
r
i
m
e
容易发现,当
p
∣
T
时,
f
(
p
∗
T
)
=
−
μ
(
T
)
/
/
最开始我以为是等于
−
f
(
T
)
,
其实并不相等
,
因为
p
可能是超过
2
次的质因数
,
此时
f
(
p
∗
T
)
应该为
0
而不是
f
(
T
)
否则
f
(
p
∗
T
)
=
−
f
(
T
)
+
μ
(
T
)
至此可线性处理
f
函数,原式
=
∑
T
=
1
n
⌊
n
T
⌋
2
f
(
T
)
,通过预处理出
f
函数的前缀和结合数论分块,时间复杂度为
O
(
n
+
n
)
题目所求式子为 \sum_{i = 1}^{n}\sum_{j = 1}^n[gcd(i, j) \in Prime],首先对该式子进行一定的化简变形。\\原式=\sum_{p\in Prime}\sum_{i = 1}^{n}\sum_{j = 1}^n[gcd(i,j)=p]\\=\sum_{p\in Prime}\sum_{i=1}^{\lfloor \frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor \frac{n}{p}\rfloor}[gcd(i,j)=1]\\化简到这里感觉有些希望,下面先进行莫比乌斯反演的套路变换\\=\sum_{p\in Prime}\sum_{i=1}^{\lfloor \frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor \frac{n}{p}\rfloor}\sum_{d|gcd(i,j)}\mu(d)\\=\sum_{p\in Prime}\sum_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\lfloor\frac{n}{pd}\rfloor^2\\至此时间复杂度降至O(\frac{n^{1.5}}{\log n}),还是过不去...\\这里式子还可以继续化简,属于一个常见的继续化简的技巧\\令T=pd,我们转而枚举T\\=\sum_{T=1}^n{\lfloor \frac{n}{T}\rfloor^2}\sum_{p|T, p\in Prime}\mu(\frac{T}{p})\\令f(T)=\sum_{p|T, p\in Prime}\mu(\frac{T}{p})\\观察f(T)的性质,发现T\in Prime时, f(T)=1\\接着我们观察一下 f(p * T)的性质, 其中p\in Prime\\ 容易发现,当p|T时,f(p * T)=-\mu(T)~~~~~//最开始我以为是等于-f(T), 其实并不相等, 因为p可能是超过2次的质因数, 此时f(p*T)应该为0而不是f(T)\\否则f(p*T)=-f(T)+\mu(T)\\至此可线性处理f函数,原式=\sum_{T=1}^n\lfloor \frac{n}{T} \rfloor^2f(T),通过预处理出f函数的前缀和结合数论分块,时间复杂度为O(n + \sqrt n)
题目所求式子为i=1∑nj=1∑n[gcd(i,j)∈Prime],首先对该式子进行一定的化简变形。原式=p∈Prime∑i=1∑nj=1∑n[gcd(i,j)=p]=p∈Prime∑i=1∑⌊pn⌋j=1∑⌊pn⌋[gcd(i,j)=1]化简到这里感觉有些希望,下面先进行莫比乌斯反演的套路变换=p∈Prime∑i=1∑⌊pn⌋j=1∑⌊pn⌋d∣gcd(i,j)∑μ(d)=p∈Prime∑d=1∑⌊pn⌋μ(d)⌊pdn⌋2至此时间复杂度降至O(lognn1.5),还是过不去...这里式子还可以继续化简,属于一个常见的继续化简的技巧令T=pd,我们转而枚举T=T=1∑n⌊Tn⌋2p∣T,p∈Prime∑μ(pT)令f(T)=p∣T,p∈Prime∑μ(pT)观察f(T)的性质,发现T∈Prime时,f(T)=1接着我们观察一下f(p∗T)的性质,其中p∈Prime容易发现,当p∣T时,f(p∗T)=−μ(T) //最开始我以为是等于−f(T),其实并不相等,因为p可能是超过2次的质因数,此时f(p∗T)应该为0而不是f(T)否则f(p∗T)=−f(T)+μ(T)至此可线性处理f函数,原式=T=1∑n⌊Tn⌋2f(T),通过预处理出f函数的前缀和结合数论分块,时间复杂度为O(n+n)
code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e7 + 10;
int mu[N], f[N], primes[N], cnt, n;
bool st[N];
void init(int n = N - 10) {
mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
mu[i] = -1;
f[i] = 1;
}
for (int j = 0; primes[j] <= n / i; j++) {
st[i * primes[j]] = true;
if (i % primes[j] == 0) {
mu[i * primes[j]] = 0;
f[i * primes[j]] = mu[i];
break;
}
mu[i * primes[j]] = -mu[i];
f[i * primes[j]] = -f[i] + mu[i];
}
}
for (int j = 1; j <= n;j ++) {
f[j] = f[j - 1] + f[j];
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
init(n);
int res = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
res = res + (n / l) * (n / l) * (f[r] - f[l - 1]);
}
cout << res << "\n";
return 0;
}