【BZOJ】2818: Gcd(欧拉函数+质数)

题目

传送门:QWQ

 

 

分析

仪仗队

呃,看到题后感觉很像上面的仪仗队。

仪仗队求的是$ gcd(a,b)=1 $

本题求的是$ gcd(a,b)=m $ 其中m是质数

把 $ gcd(a,b)=1 $ 变形成 $ gcd(a,b)*m=m $

然后在n的范围内枚举一下,使 $ gcd(a,b)*m <= n $

再像仪仗队那样用欧拉函数搞一搞。

没了。

 

 

代码

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e7+3e6;
int n,pri[maxn],isp[maxn],cnt;
int phi[maxn];
int prime(){
    for(int i=1;i<=n;i++) isp[i]=1;
    for(int i=2;i<=n;i++){
        if(!isp[i]) continue;
        pri[++cnt]=i;
        for(int j=i+i;j<=n;j+=i)
            isp[j]=0;
    }
}
void Phi(){
    memset(phi,0,sizeof(phi));
    phi[1]=1;
    for(int i=2;i<=n;i++){
        if(phi[i]) continue;
        for(int j=i;j<=n;j+=i){
            if(!phi[j]) phi[j]=j;
            phi[j]=phi[j]/i*(i-1);
        }
    }
}
long long sum[maxn]; 
int main()
{
    cnt=0;
    long long ans=0;
    scanf("%d",&n);
    Phi(); prime();
    pri[0]=1;
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+phi[i];
    for(int i=1;i<=cnt;i++) ans+=(long long)2*sum[n/pri[i]]-1;
    
    printf("%lld\n",ans);
    return 0;
}

 

 

posted @ 2018-06-05 20:46  noble_(noblex)  阅读(209)  评论(0编辑  收藏  举报
/* */