首页 > 其他 > 详细

[BZOJ2818]GCD

时间:2018-11-08 15:50:36      阅读:197      评论:0      收藏:0      [点我收藏+]

[BZOJ2818]GCD

BZOJ
luogu
\[\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)是质数]\]
考虑枚举n以内的质数k(\(10^7\)内大概70万个)
那么每个质数k的贡献\[\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=k]\]
\[=\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{k}\rfloor}[gcd(i,j)=1]\]
\[=2\sum_{i=2}^{\lfloor\frac{n}{k}\rfloor}\phi(i)+1\]
所以相当于求\[\sum_k[2\sum_{i=2}^{\lfloor\frac{n}{k}\rfloor}\phi(i)+1]\]
其中k是小于等于n的质数
可以线性筛素数,筛\(\phi\)之后暴力求解,复杂度大概是个什么鬼调和级数?
但是发现\(\phi\)前缀和一下就可以线性了(实测并没有快...)
听说还有根号做法?

#define ll long long
#include<bits/stdc++.h>
using namespace std;
const int _=1e7+5;
int n,cnt;
int p[700000];
ll ans,phi[_];
bool vis[_];
int main(){
    cin>>n;phi[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i])p[++cnt]=i,phi[i]=i-1;
        for(int j=1;j<=cnt&&p[j]*i<=n;j++){
            int v=p[j]*i;vis[v]=1;
            if(i%p[j]==0){phi[v]=p[j]*phi[i];break;}
            phi[v]=(p[j]-1)*phi[i];
        }
    }
    for(int i=3;i<=n>>1;i++)phi[i]+=phi[i-1];
    ans=cnt;
    for(int i=1;i<=cnt;i++)
        if(n/p[i]>=2)ans+=phi[n/p[i]]<<1;
    cout<<ans<<endl;
    return 0;
}

[BZOJ2818]GCD

原文:https://www.cnblogs.com/sdzwyq/p/9929177.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!