【学习记录】线性(欧拉)筛

本文介绍了欧拉筛法的原理及其在解决积性函数问题中的应用。通过示例代码展示如何实现欧拉筛,并解释了在编程过程中需要注意的细节,如防止数据类型溢出和终止条件的正确设置。此外,还提到了递归思想在理解题目和解题过程中的重要作用。
摘要由CSDN通过智能技术生成

集训的确很有助于提升实力,蒟蒻的我也有不小的收获233

在做一道 '积性函数' 的题的时候用到了它

(虽然打完表当时我就看不懂题了,之后经过讲解才明白那是个递归思想来的递归推导式)

  • 欧拉筛的原理是,将一个自然数分解为其最小质因子与一个合数(或者质数的乘积)
  • 参考 '质数唯一分解定理' ,不了解请自行百度(也就是我们其实还可以将这个合数再次分解为其他质因数的k次方的连乘 )
  • 能力尚且有限,详细写在注释里了,可供一样在学的朋友参考

-code-

#include <iostream>

using namespace std;
typedef long long ll;
void faster_read() {
    ios::sync_with_stdio(false);
    //cin.tie(0); //同步输入输出,也就是输入完了才输出;
    //cout.tie(0); //特殊情况下会拖慢很多时间;
}

ll primes[1000001];
bool p_mark[1000001]; //bool类型或char类型占一字节(char类型不代表必须是字符,我们只是用它的值)

ll eluer_prime(ll maxNum)
{
    ll p_cnt=0;
    for (int i = 2; i < maxNum; ++i) {
        if (!p_mark[i]) primes[p_cnt++]=i;
        for (int j = 0; (primes[j]<i*maxNum) && (j<p_cnt) ; ++j){
            p_mark[i* primes[j]]=true;
            if (i% primes[j]==0) break;
        }
    }
    return p_cnt;
}
//三个内层循环结束条件:
//1. [i*primes[j]<maxNum(看需求可以换成'<='), 防止越界,这里不要用除法,用除法因为向下取整会导致筛除出错] ;
//2. [j<p_cnt, p_cnt是动态更新的质数表长度,此语句防止素数表越界] ;
//3. [i%primes[j]!=0,最关键的一步,当前的i可被当下primes[j]整除,此时需要停止标记,否则会有重复筛除] ;
//      例如i=8,素数序列为2,3,5,7,primes[j]==2时i/primes[j]==0,应当停止,如果继续,下一个筛除的数是3*8=24,但24应该由12筛除 ;
//      按照原理,它应该是一个最小质因数与一个合数(质数)的乘积这种唯一分解,对于24,其最小质因子应是2;
//      类推得到,如果在这时候不停止筛除,接下来筛除的数被大于其最小质因子的prime[j+1]筛除一次,而i到其分解的非最小质因子部分时就会对该数进行额外筛除,拖慢效率;
//      而prime[j+1]不是筛除数的最小质因子,也不再满足原理了 ;
int main()
{
    faster_read();
    ll pn=eluer_prime(30);
    cout<<pn<<'\n';
    for (int i = 0; i < pn; ++i) {
        cout<<primes[i]<<' ';
    }
}

*注意需要的数据是否会爆了某个表达式,如果会爆那么就转化成long long来运算,同时注意其他数据类型会不会导致溢出或丢失精度。

*修改了一下之前的错误,终止条件不能写成primes[j]=maxNum/i,这么写会导致判断出错,筛除出现纰漏!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值