快速线性筛法

  • 快速线性筛法

    ​ 仔细分析埃拉托斯特尼筛法可发现,这种方法会造成重复筛除合数,影响效率。以 30 为例,在 i=2 的时候,k=2*15 筛了一次;在i=5,k=5*6 的时候又筛了一次。为避免冗余,提高效率,也就有了快速线性筛法,其可保证不会重复删除一个数。

    ​ 根据算术的基本定理——每个合数都可以以唯一形式被写成质数的乘积,所以我们可以把所有素数的集合看成一个“盒子”,那么所有合数其实就是重复从素数这个“盒子”中取两个及以上不分顺序的组合,还是以30为例,我们有235、253、325、352、523、532,共6种取法,在埃拉托斯特尼筛法中,235和325对应6*5、253和523对应10*3、352和532对应15*2,所以共重复了三次。为了不重复取到相同的合数,我们需要一种从素数“盒子”中取素数的取法,这种取法不会因为合数的素数组合相同而顺序不同而取多次

    ​ 接下来开始介绍快速线性筛法是如何从素数“盒子”中取素数才不会重复的:

    ​ 首先我们是筛法所以素数是从小到大按顺序获取的。假设我们已有一个素数序列从小到大排列,例如2、3、5、7,对于由两个素数组成的合数,第一个素数我们可以从小到大取,第二个素数就从最小的素数取到等于第一个素数为止,即22,32,33,52,53,55以此类推,新加入素数时,与新素数相关的合数,只须算新素数分别与小于等于它的素数一遍即可(明确一些条件,即一个合数肯定由小于它的素数组成,一个素数和其他素数的组合肯定大于该素数,所以与新素数有关的合数肯定在新素数之后),接下来是三个素数组成的合数,首先,遇到三素数组成的合数必然先遇到由其中两素数组成的合数(因为三素数中两个素数的积肯定比三素数的积小),例如遇到222之前肯定先遇到22,遇到332和322之前肯定先遇到32,在两个素数的合数的基础上,第三个素数我们只需要从小到大乘到该合数最小的素数即可,例如72就只和2相乘,73就可以和3与2,没必要将72乘以3会和73乘2时重复,四及以上素数的合数同理,以2,3,5为例按以上取法结果为:

    两个素数的合数组合:22,32,33,52,53,55

    三个素数的合数组合:222,322,332,333,522,532,533,552,553,555

    ​ 如此保证不会如埃拉托斯特尼筛法一样重复筛选同一合数。

    #include<vector>
    vector<int> get_prime(int n)
    {
        vector<int> prime;
        prime.clear();
        int cnt=0;
        int size;
        bool* p=new bool[n+1];
        p[0]=p[1]=false;		//0和1不是质数也不是合数
        
        for(int i=2;i<n;i++)
            p[i]=true;
        for(int i=2;i<=n;i++)
        {
            if(p[i])
                prime.push_back(i);
            size=prime.size();
            for(int j=0;j<size&&prime[j]*i<=n;j++)
            {
                p[prime[j]*i]=false;
                if(i%prime[j]==0)//若能整除说明该合数包含该素数,且该合数的最小素数为该素数
                    break;
            }
        }
        delete[]p;
        return prime;
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值