• 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' 就和前面重复了。

  • 相关阅读:
    搜索引擎ElasticSearch系列(四): ElasticSearch2.4.4 sql插件安装
    搜索引擎ElasticSearch系列(三): ElasticSearch2.4.4 bigdesk插件安装
    搜索引擎ElasticSearch系列(二): ElasticSearch2.4.4 Head插件安装
    搜索引擎ElasticSearch系列(一): ElasticSearch2.4.4环境搭建
    LumiSoft.Net 收发邮件
    搜索引擎Solr6.2.1 索引富文本(word/pdf/txt/html)
    用异或提取出数组中的单独数
    买卖股票的最佳时机 II
    二叉树的路径总和
    SpringBeanUtils的部分方法类
  • 原文地址:https://www.cnblogs.com/jeakeven/p/4564783.html
Copyright © 2020-2023  润新知