ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

欧拉筛【转载自用

2021-05-22 10:04:10  阅读:216  来源: 互联网

标签:约数 转载自 nn int void reg 欧拉


前言  https://www.luogu.com.cn/blog/HSH/post-shuo-lun-ou-la-shai-fa

最近学数论,我是真的绝望,欧拉筛法也只能靠背代码勉强凑合凑合,但在我社CSQ大佬的帮助下,我理解到了其中神奇的奥妙


正题

欧拉筛法是一种可以筛出质数,欧拉函数,约数个数和约数和的筛法 那么我们就对这些问题逐一进行讲解

在这之前,我们先说几个东西:

1、每一个大于等于2的正整数nn,都有n=p_1^{w_1}p_2^{w_2}…p_m^{w_m}n=p1w1​​p2w2​​…pmwm​​(p_1p1​到p_mpm​按升序排列)

2、正整数nn的欧拉函数phi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})…(1-\frac{1}{p_m})=p_1^{w_1-1}(p_1-1)*p_2^{w_2-1}(p_2-1)*…*p_m^{w_m-1}(p_m-1)phi(n)=n(1−p1​1​)(1−p2​1​)…(1−pm​1​)=p1w1​−1​(p1​−1)∗p2w2​−1​(p2​−1)∗…∗pmwm​−1​(pm​−1)

3、正整数nn的约数个数d(n)=(1+w_1)(1+w_2)…(1+w_m)d(n)=(1+w1​)(1+w2​)…(1+wm​)

4、正整数nn的约数和s(n)=(1+p_1+p_1^2+…+p_1^{w_1})(1+p_2+p_2^2+…+p_2^{w_2})……(1+p_m+p_m^2+…+p_m^{w_m})s(n)=(1+p1​+p12​+…+p1w1​​)(1+p2​+p22​+…+p2w2​​)……(1+pm​+pm2​+…+pmwm​​)

质数

 

代码

inline void sieve(int x) {
    for(reg int i = 2;i <= x;i ++) {
        if(! vis[i])
            prim[++ len] = i;
        for(reg int j = 1;j <= len && i * prim[j] <= x;j ++) {
            vis[i * prim[j]] = 1;
            if(i % prim[j] == 0)
                break;
        }
    }
}

欧拉函数

 

代码

inline void sieve(int x) {
    phi[1] = 1;
    for(reg int i = 2;i <= x;i ++) {
        if(! vis[i]) {
            prim[++ len] = i;
            phi[i] = i - 1; //因为欧拉函数代表小于这个数的且与这个数互质的数的个数,所以质数的欧拉函数为它本身减1
        }
        for(reg int j = 1;j <= len && i * prim[j] <= x;j ++) {
            vis[i * prim[j]] = 1;
            if(i % prim[j] == 0) {
                phi[i * prim[j]] = phi[i] * prim[j];
                break;
            }
            phi[i * prim[j]] = phi[i] * (prim[j] - 1);
        }
    }
}

约数个数

 

代码

inline void sieve(int x) {
    for(reg int i = 2;i <= x;i ++) {
        if(! vis[i]) {
            prim[++ len] = i;
            d[i] = 2;   //质数的约数只有1和它本身
            sum[i] = 1;
        }
        for(reg int j = 1;j <= len && i * prim[j] <= x;j ++) {
            vis[i * prim[j]] = 1;
            if(i % prim[j] == 0) {
                sum[i * prim[j]] = sum[i] + 1;
                d[i * prim[j]] = d[i] / (sum[i] + 1) * (sum[i] + 2);
                break;
            }
            sum[i * prim[j]] = 1;
            d[i * prim[j]] = d[i] * 2;
        }
    }
}

约数和

 

代码

inline void sieve(int x) {
    for(reg int i = 2;i <= x;i ++) {
        if(! vis[i]) {
            prim[++ len] = i;
            psum[i] = s[i] = i + 1;
        }
        for(reg int j = 1;j <= len && i * prim[j] <= x;j ++) {
            vis[i * prim[j]] = 1;
            if(i % prim[j] == 0) {
                psum[i * prim[j]] = psum[i] * prim[j] + 1;
                s[i * prim[j]] = s[i] / psum[i] * psum[i * prim[j]]
                break;
            }
            psum[i * prim[j]] = prim[j] + 1;
            s[i * prim[j]] = s[i] * psum[i * prim[j]];
        }
    }
}

 

标签:约数,转载自,nn,int,void,reg,欧拉
来源: https://www.cnblogs.com/donkey9/p/14798156.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有