Algorithm --> 筛法求素数


一般的线性筛法

genPrime和genPrime2是筛法求素数的两种实现,一个思路,表示方法不同而已。

#include<iostream>  
#include<math.h>  
#include<stdlib.h>
using namespace std; const int MAXV = 100; //素数表范围 bool flag[MAXV+1]; //标志一个数是否为素数 int prime[MAXV+1]; //素数表,下标从0开始 int size=0; //素数个数
void genPrime(int max) { memset(flag, true, sizeof(flag));//首先对标签数组进行初始化,全部设为true。 for(int i = 2; i <= max / 2; i++) { /* 从2开始,删除2的倍数 */ if(flag[i]) { //j=i<<1等价于 j=i*2,即j是i的两倍,而最后的j+=i,则表示下一个循环j是i的3倍,接着4倍。。。 //i的所有2~N倍数肯定都不是素数,因此将flag置为0,直到最后一位。 for(int j = i << 1 ; j <= max; j += i) { flag[j] = false; } } } for(int i = 2 ; i <= max; i++) { if(flag[i]) { prime[size++] = i;//存储素数。将所有标志位依然为1的标志写入素数数组中去。 } } }
void genPrime2(int max) { memset(flag, true, sizeof(flag));//首先对标签数组进行初始化,全部设为true。 int sq=sqrt((double)max)+1; //一个数 n 如果是合数,那么它的所有的因子不超过sqrt(n) int i,j, k; for(i = 2;i<=sq; i++) { if(flag[i]) for(j=2,k=max/i+1;j<k;j++) flag[i*j] = false; //所有i的j倍都不是素数 } for( i = 2 ; i <= max; i++) { if(flag[i]) { prime[size++] = i;//存储素数。将所有标志位依然为1的标志写入素数数组中去。 } } }
int main() { // genPrime(MAXV); genPrime2(MAXV); //输出所有素数。 for(int i=0;i<size;i++) cout<<prime[i]<<" "; cout<<endl; system("pause"); return 0; } /* 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 请按任意键继续. . . */

快速线性筛法

快速线性筛法没有冗余,不会重复筛除一个数,所以“几乎”是线性的。

#include<iostream>
using namespace std; 
const long N = 200000; long prime[N] = {0},num_prime = 0; int isNotPrime[N] = {1, 1};
int main() { for(long i = 2 ; i < N ; i ++) { if(! isNotPrime[i]) prime[num_prime ++]=i; //关键处1 for(long j = 0 ; j < num_prime && i * prime[j] < N ; j ++) { isNotPrime[i * prime[j]] = 1; if( !(i % prime[j] ) ) //关键处2   break; } } return 0; }

首先,先明确一个条件,任何合数都能表示成一系列素数的积。

不管 i 是否是素数,都会执行到“关键处1”,

  ①如果 i 都是是素数的话,那简单,一个大的素数 i 乘以不大于 i 的素数,这样筛除的数跟之前的是不会重复的。筛出的数都是 N=p1*p2的形式, p1,p2之间不相等

  ②如果 i 是合数,此时 i 可以表示成递增素数相乘 i=p1*p2*...*pn, pi都是素数(2<=i<=n), pi<=pj ( i<=j ),p1是最小的系数。

根据“关键处2”的定义,当p1==prime[j] 的时候,筛除就终止了,也就是说,只能筛出不大于p1的质*i。

直观地举个例子。i=2*3*5

此时能筛除 2*i ,不能筛除 3*i

如果能筛除3*i 的话,当 i' 等于 i'=3*3*5 时,筛除2*i' 就和前面重复了。

优质内容筛选与推荐>>
1、[BZOJ5251][九省联考2018]劈配(网络流)
2、django Model模型二及Model模型对数据库的操作
3、最大子序列
4、递归算法Recursion
5、css3的box-sizing


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn