• 关于埃式筛法的极限优化


    摘自https://blog.csdn.net/qq_43332305/article/details/82959066

    关于素数的普通筛法想必大家都清楚。使用一个数组vis[n],从2遍历到n-1,每次碰到素数就把它的倍数剔除。这里有三种手段可以大大降低埃式筛法的时间复杂度:
    先发埃式筛法模板,假设初始化vis所有成员为0,0代表是素数,1代表不是素数:

    1 for(int i=2;i<=N;i++){
    2         if(!vis[i]){
    3             for(int j=2*i;j<=N;j+=i){
    4                 vis[j]=1;
    5             }
    6         }
    7     }


    那么首先会想到一个问题,一个合数如果有因数,那么必定是成对存在,也就是筛子只用判断其中一个因数就可以了,比如15=3*5,在3的时候已经把15给筛掉了,何必去循环到5呢?于是优化如下,循环到根号n即可。

    1 for(int i=2;i*i<=N;i++){//将i<=N换成i*i<=N
    2         if(!vis[i]){
    3             for(int j=2*i;j<=N;j+=i){
    4                 vis[j]=1;
    5             }
    6         }
    7     }


    接下来是第二重优化。第二层循环中不是从j=2i开始,每次增加一个i,即剔除i的所有倍数吗?试想一下,6是不是被2筛过了,此时碰到素数3又要筛一遍。而j从2i到i*i,即2倍到i倍的变化,在第一层循环中,2~i-1已经把他们的素数倍数筛完,所以结论如下:
    第i个数只用筛从 i 乘 i 开始到n的每个数,而不用从 2 乘 i 开始
    接下来优化代码:

    1 for(int i=2;i*i<=N;i++){//将i<=N换成i*i<=N
    2         if(!vis[i]){
    3             for(int j=i*i;j<=N;j+=i){//将2*i换成i*i
    4                 vis[j]=1;
    5             }
    6         }
    7     }

    第三重优化是一个很小的改动与优化,在第二重循环中,每次增加素数的1倍,但除了2以外素数都是奇数,那么奇数乘以偶数是偶数,偶数情况早已被2筛完,故每次增加2i倍.

    1 for(int i=2;i*i<=N;i++){//将i<=N换成i*i<=N
    2         if(!vis[i]){
    3             int mul;//倍数
    4             i==2?mul=1:mul=2;
    5             for(int j=i*i;j<=N;j=j+i*mul){//将2*i换成i*i
    6                 vis[j]=1;
    7             }
    8         }
    9     }
  • 相关阅读:
    iOS_核心动画(二)
    iOS_核心动画CALayer(一)
    iOS_KVC与KVO
    iOS_Quartz 2D绘图
    iOS_触摸事件与手势识别
    iOS_多线程(二)
    iOS_多线程(一)
    iOS_UIAlertController
    CTF-Pwn-[BJDCTF 2nd]diff
    数据结构--队列(Java实现)
  • 原文地址:https://www.cnblogs.com/codeoosacm/p/10116749.html
Copyright © 2020-2023  润新知