zoukankan      html  css  js  c++  java
  • 素数筛选法

    当一个数不算大的时候,可以用普通的求素数的方法去求,但是如果一个数过大的话,就像让求1-十亿之间素数的个数,普通方法就不行了,这事就需要用到素数筛选法,他的时间复杂度是O(n),尽管不算很好,但是,也算是目前为止比较快的一种方法了,它是以空间换取时间,现在的计算机,空间有的是,但是时间是非常珍贵的。效率问题特别重要。他的原理就是标记,防止重复判断,这样提高了效率。就像2是素数,所有是2的倍数的肯定都不是素数,这时候标记上,接着判断3是素数,所有是3的倍数的都肯定不是素数,这时就要标记上,以此下去,执行到根下(总数),这样就会得到一个素数表,所有没有被标记的都是素数,下面是具体的代码实现,代码里面有注释。写的很清楚。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #define MAX 1000000000//定义一个数组长度
     5 bool prime[MAX + 1];//素数表
     6 int main()
     7 {
     8     int i, j, count = 0;//count为计数器
     9     memset(prime, true, sizeof(prime));//初始化,将prime数组全部都初始化为true
    10     prime[0] = prime[1] = false; prime[2] = true;//0,1都不是素数,所以为false,2是素数,所以为true
    11     for(i = 2; i * i <= MAX; i ++)/*从2开始进行遍历, i * i <= MAX 就等价于 i < sqrt(MAX);但是前者更不容易出错
    12      具体为什么是sqrt就不用说了吧,普通的方法中也有这个*/   
    13     {
    14         if(prime[i])//如果没有被标记的话将它的倍数的数标记(标记就是将它赋值为false)
    15         {
    16             for(j = i + i; j <= MAX; j += i)//因为是从2开始的,所以j = i * i 就行了,最小的一个他的倍数的就是i * i了,不可能有比这个更小的了
    17                 prime[j] = false;//标记为false
    18         }
    19     }
    20     for(i = 2; i <= MAX; i ++)//遍历一下,找出所有的素数来
    21         if(prime[i])
    22                 count ++;//如果没有被标记,计数器++
    23     printf("count is :%d
    ", count);
    24     return 0;
    25 }

    这时最基础的,当然还可以进行改进,改进的越多,执行效率就越快,例如:因为偶数不可能为素数,它是肯定能被2整除的,所以可以舍掉所有的偶数,这样会减少一半的时间,当然空间也会减少一半,如果十亿的话,开个5亿的数组就行了,for循环中的i 应该是从3开始了,然后一次加2,这样标记会更快,具体代码就不实现了。大致原理差不多。这时一个非常基础的算法。素数也是用到的比较多的。当然也可以琢磨点在改进改进,目前为止我没有想到更好的,如果有哪位大神有更好的方法,麻烦留一下言告知一下,谢谢!

  • 相关阅读:
    Vpython简单例子
    我在读的书:《ACM图灵奖:19662006(第三版)计算机发展史的缩影》
    可惜啊,没见到姚期智~~
    The Sounds of Music 观后感
    终于在博客园申请开通博客了
    【引用】Python open读写文件实现脚本
    在Python中使用中文
    Discovery:深入理解计算机系统 (Ver.2) 中文版
    [导入]一个都不能少:全面认识IE插件
    [导入]午间心情
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/3945064.html
Copyright © 2011-2022 走看看