• [BZOJ 2818] Gcd


    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2818

    Algorithm:

    一道比较水的数论题

    可以发现只要找到所有素数,对于每个素数计算出1~n/p的互质的数的个数

    一看到互质,联想到欧拉函数

    预处理欧拉函数的前缀和,结果为sigma(pre[n/prime[i]]*2-1)  (有序数对,舍去(1,1)特解)

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    
    const int MAXN=1e7+10;
    bool mark[MAXN];
    int n,prime[MAXN],phi[MAXN],cnt=0;
    ll pre[MAXN],res=0;
    
    void Getphi()
    {
        phi[1]=1; //线性筛
        for(int i=2;i<=n;i++)
        {
            if(!mark[i]) prime[++cnt]=i,phi[i]=i-1;
            for(int j=1;j<=cnt;j++)
            {
                if(prime[j]*i>n) break;
                mark[prime[j]*i]=true;
                if(i%prime[j]==0){phi[i*prime[j]]=prime[j]*phi[i];break;}   //保证复杂度的关键
                else phi[i*prime[j]]=phi[i]*phi[prime[j]];
            }
        }
    }
    
    int main()
    {
        cin >> n;
        Getphi();
        
        for(int i=1;i<=n;i++)
            pre[i]=pre[i-1]+phi[i];
        for(int i=1;i<=cnt;i++)
            res+=pre[n/prime[i]]*2-1;
        cout << res;
        return 0;
    }

    Review:

    1、互质数对数    ----->     欧拉函数

    2、线性筛

    其中i%prime[j]=0时break是保证复杂度的关键

    这样才能保证每个合数都由自己最小的质因数更新 ( 证明:https://wenku.baidu.com/view/2d706761aa00b52acec7ca63.html )

    同时线性筛和素数筛在筛的顺序上有差异,线性筛是先广度,素数筛是先深度(原因在于phi[i]要先求出)

  • 相关阅读:
    Android中this.*与*.this还有*.class的区别是什么?
    多线程之CEvent
    Java类型信息之RTTI
    javascript学习-闭包
    javascript学习-对象与原型
    javascript学习-类型判断
    Javascript学习-简单测试环境
    javascript学习-目录
    MySQL数据库安装与配置详解
    深入研究C语言 第四篇
  • 原文地址:https://www.cnblogs.com/newera/p/9050597.html
Copyright © 2020-2023  润新知