【数论】BZOJ 2818 Gcd
这道题看起来是一道很水的数论题
实际上就是一道很水的数论题Σ( ° △ °
若
G
c
d
(
x
,
y
)
=
p
Gcd(x,y)=p
Gcd(x,y)=p,则
G
c
d
(
x
/
p
,
y
/
p
)
=
1
Gcd(x/p,y/p)=1
Gcd(x/p,y/p)=1
所以我们枚举素数
p
p
p,求出
N
/
p
N/p
N/p以内的互质的数的对数,然后每一个
p
p
p之下的答案求和就是最终答案
而欧拉函数的意义就是这个数以内与它互质的数的个数,所以我们把 p h i [ 1 ] phi[1] phi[1]到 p h i [ N / p ] phi[N/p] phi[N/p]加起来就是 N / p N/p N/p以内的互质的数的对数,筛出来之后用个前缀和就可以了。
由于这个数对是有序的,每次我们*2再减1(1,1的情况)就可以了
另外学校OJ的要求高一些 所以把phi和前缀和数组合并到了一起,否则会MLE
#include<cstdio>
#define LL long long
#define MAXN 10000005
int n,pn,prime[MAXN];
bool vis[MAXN];
LL ans,phi[MAXN];
void sieve()
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
phi[i]=i-1;
prime[++pn]=i;
}
for(int j=1;j<=pn&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
int main()
{
scanf("%d",&n);
sieve();
for(int i=1;i<=n;i++)
phi[i]=phi[i-1]+phi[i];
for(int i=1;i<=pn;i++)
ans+=phi[n/prime[i]]*2-1;
printf("%lld\n",ans);
return 0;
}