• [BZOJ2818]GCD


    [BZOJ2818]GCD

    BZOJ
    luogu
    求$$sum_{i=1}nsum_{j=1}n[gcd(i,j)是质数]$$
    考虑枚举n以内的质数k((10^7)内大概70万个)
    那么每个质数k的贡献$$sum_{i=1}nsum_{j=1}n[gcd(i,j)=k]$$

    [=sum_{i=1}^{lfloorfrac{n}{k} floor}sum_{j=1}^{lfloorfrac{n}{k} floor}[gcd(i,j)=1] ]

    [=2sum_{i=2}^{lfloorfrac{n}{k} floor}phi(i)+1 ]

    所以相当于求$$sum_k[2sum_{i=2}^{lfloorfrac{n}{k} floor}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;
    }
    
  • 相关阅读:
    招行面试
    今日头条面试[教育岗]
    四方精创 面试
    ArrayList 源码
    redis缓存,穿透,击穿,雪崩
    hashMap
    集合整理
    阿里CBU技术部一面
    网安面试
    php递归获取顶级父类id
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/9929177.html
Copyright © 2020-2023  润新知