利用线性筛法求素数的方法顺便求解1~n的欧拉函数的全过程

相关链接:线性筛法素数的方法见我的博客文章埃氏筛法和线性筛法求素数.
先看题目:筛法求欧拉函数
在这里插入图片描述
  分析:
  如果用分解质因数的方法求解欧拉函数之和,需要大约O(n*sqrt(n))的时间复杂度,为了更为高效的求解1~n中每个数的欧拉函数,我们可以利用欧拉函数的性质,这样O(n)的时间复杂度便能解决问题,看算法的魅力!
  具体性质如下图(还是手写数学式子方便,凑合看手稿吧):
在这里插入图片描述

在这里插入图片描述
  基于以上三个性质,我们可以在欧拉筛素数的过程中完成对每一个数的欧拉函数的计算。具体如代码:

//在线性欧拉筛素数的基础上计算欧拉函数,巧妙,效率高。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1000000+7;
int primes[N],phi[N];
bool st[N];
LL getEulers(int n){
    phi[1] = 1;
    int cnt = 0;
    for(int i = 2;i<= n; i++){
        if(!st[i]){
            primes[++cnt] = i;
            phi[i] = i-1;      //性质1
        }
        for(int j = 1;j<= cnt && primes[j]*i <=n; j++){
            st[primes[j] * i] = true;
            if(i % primes[j] == 0){
                phi[primes[j] * i] = primes[j] * phi[i];   //性质2
                break;
            }
            else{
                phi[primes[j] * i] = (primes[j] - 1) * phi[i];   //性质3
            }
        }
    }
    LL ans = 0;
    for(int i = 1; i<= n; i++){
        ans = ans + phi[i];
    }
    return ans;
}
int main(){
    int n;
    scanf("%d",&n);
    LL ans = getEulers(n);
    printf("%lld",ans);
    return 0;
}

好了,全文结束,如有不当之处还请看官多多批评指正。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值