题意
给你一个n,请问有多少个 1 ≤ i , j ≤ n 1 \le i, j\le n 1≤i,j≤n,gcd(i, j)是一个质数。这里的i,j是无序的。
思路
首先我们要先清楚gcd的含义
由于算术定理:
x
=
p
1
a
1
∗
p
2
a
2
∗
p
3
a
3
.
.
.
∗
p
k
a
k
.
a
=
p
1
a
1
∗
p
2
a
2
∗
p
3
a
3
.
.
.
∗
p
k
a
k
.
b
=
p
1
b
1
∗
p
2
b
2
∗
p
3
b
3
.
.
.
∗
p
k
b
k
.
g
c
d
(
a
,
b
)
=
x
=
p
1
m
i
n
(
a
1
,
b
1
)
∗
p
2
m
i
n
(
a
2
,
b
2
)
∗
p
3
m
i
n
(
a
3
,
b
3
)
.
.
.
∗
p
k
m
i
n
(
a
k
,
b
k
)
(
a
m
o
d
p
i
=
,
b
m
o
d
p
i
=
0
)
x = p_1^{a_1} * p_2^{a_2} * p_3^{a_3} ...*p_k^{a_k} \\.\\a = p_1^{a_1} * p_2^{a_2} * p_3^{a_3} ...*p_k^{a_k}\\.\\b = p_1^{b_1} * p_2^{b_2} * p_3^{b_3} ...*p_k^{b_k}\\.\\gcd(a, b) = x = p_1^{min(a_1, b_1)} * p_2^{min(a_2, b_2)} * p_3^{min(a_3, b_3)} ...*p_k^{min(a_k, b_k)}(a \ mod \ p_i = , b \ mod \ p_i = 0)
x=p1a1∗p2a2∗p3a3...∗pkak.a=p1a1∗p2a2∗p3a3...∗pkak.b=p1b1∗p2b2∗p3b3...∗pkbk.gcd(a,b)=x=p1min(a1,b1)∗p2min(a2,b2)∗p3min(a3,b3)...∗pkmin(ak,bk)(a mod pi=,b mod pi=0)
换句话说,gcd(a, b)是a,b所共有因子且取个数最小的乘积。
由于题意所说gcd(a, b)是一个质数d,那么我们就要清楚a,b除了只有一个共同因子d(d的次数为1)意外没有任何一个共同因子。这就等价于
g
c
d
(
a
d
,
b
d
)
=
1
gcd(\frac{a}{d}, \frac{b}{d}) = 1
gcd(da,db)=1,那么我们只需要去找有多少对互质的数就行了。那么我们对于一个数列而言,它的欧拉函数总和,就是两个互质数对个数。可以看我的算法笔记。我们可以枚举出
1
0
7
10^7
107以内所有的质数。然后让n除上每一个质数,得到p我们要求的是1~p以内有多少对互质的数,也就是对
ϕ
(
i
)
\phi(i)
ϕ(i)求一个前缀和。
PS:这个题目没有前缀和处理phi[1] = 1只是加1,不加2是因为x x本身顺序根本没有关系。
代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long
#define endl "\n"
#define xx first
#define yy second
using namespace std;
const int N = 1e7 + 10;
int n;
int cnt, pr[N], phi[N], sum[N];
bool st[N];
void getprime(int x)
{
phi[1] = 1;
for(int i = 2; i <= x; i ++)
{
if(!st[i])
{
pr[cnt++] = i;
phi[i] = i-1;
}
for(int j = 0; pr[j]*i <= x; j ++)
{
st[pr[j] * i] = 1;
if(i % pr[j] == 0)
{
phi[i * pr[j]] = phi[i] * pr[j];
break;
}
phi[i * pr[j]] = phi[i] * (pr[j] - 1);
}
}
for(int i = 2; i <= N; i ++) sum[i] = sum[i-1] + phi[i];
}
signed main()
{
IOS;
int ans = 0;
cin >> n;
getprime(n);
for(int i = 0; i < cnt; i ++)
{
int now = n / pr[i];
ans += sum[now] * 2 + 1;
}
cout << ans << endl;
return 0;
}