洛谷P2568 GCD(欧拉筛,欧拉函数)
思路
遇到在范围内
g
c
d
(
a
,
b
)
=
k
gcd(a,b)=k
gcd(a,b)=k,我一般会把式子转化为
g
c
d
(
a
/
k
,
b
/
k
)
=
1
gcd(a/k,b/k)=1
gcd(a/k,b/k)=1后使用欧拉函数求解,本题只需要筛出质数,将范围
1
−
N
1-N
1−N映射到
1
−
N
/
p
r
i
m
e
[
1
]
,
1
−
N
/
p
r
i
m
e
[
2
]
.
.
.
1- N/prime[1],1-N/prime[2]...
1−N/prime[1],1−N/prime[2]...,然后在每个新范围内求出互质的数的个数对即可,而求互质的数对
(
a
,
b
)
(a,b)
(a,b)的个数我们可以假定
a
<
b
a<b
a<b,这样对
1
−
b
1-b
1−b内所有数求其欧拉函数就能得到互质的数有几对,由于
(
4
,
2
)
,
(
2
,
4
)
(4,2),(2,4)
(4,2),(2,4)都合法,因此最后答案乘2再减1即可
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+6;
int prime[N],phi[N],sum[N],cnt;
bool vis[N];
void init(int n)
{
vis[1]=true;
phi[1]=1;
sum[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i]) prime[++cnt]=i,phi[i]=i-1;
for(int j=1;prime[j]*i<=n;j++)
{
vis[prime[j]*i]=true;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
sum[i]=sum[i-1]+phi[i];
}
}
signed main()
{
int n;
cin>>n;
init(n+3);
int res=0;
for(int i=1;i<=cnt;i++)
{
int p=prime[i];
if(p>n) break;
int l=1,r=n/p;
res=res+2*sum[r]-1;
}
cout<<res<<endl;
return 0;
}