筛选质数

来源:互联网 发布:北京seo公司哪家好 编辑:程序博客网 时间:2024/06/05 02:14

关于怎么判断一个数 是否是质数,最简单的方法是枚举 2 到 n1,判断是否是 n 的约数。如果是, n 肯定不是一个质数。再仔细想想,如果 a 是 n 的一个约数,那么必然有一个b 满足 anan 和 bn 中必然有一个成立,因为如果a>n 并且 b>n,那么 ab>n,和 an 矛盾。因此如果 n 是一个合数,那么我们只需要枚举到 n 就一定能找到 n的一个约数。否则,n 肯定是一个质数。下面是代码:

int is_prime(int n){   for(int i = 2; i * i <= m; i++)      if(n % i == 0)         return 0;//不是质数    return 1;//是质数}

更多的时候,需要预处理出一段区间上的质数,如果按照之前的方法一个一个判断,时间上肯定会承受不了。于是提出了一种预处理1N上质数的算法,称为 Eratosthenes 筛选。

素数筛选算法的基本思想是我们先假设 2 到 N 所有数都是素数。我们从 2 开始扫描,对于一个数 i,可以得到2i3i ……ki 都不是素数,因为这些数都有 i 这个因子,表示这些数不是素数,一直枚举到 N。对于每一个合数,它至少会被它的一个因子枚举到,所以可能证明这个算法的正确性。接下来分析时间复杂度,对于每个 i,枚举的次数为 n / i,所以总时间复杂度为N/2 + N/3 + … + N/N = O(NlgN) 。

       下面是代码:

for(int i = 2; i <= n; i++){   is_prime[i] = 1; }for(int i = 2; i <= n; i++){   for(int j = i * 2; j <= n; j += i)      {         is_prime[j] = 0;      }}

       上面的代码便筛选出来了 n 以内的素数,如果 is_prime[i] = 1i 是素数,否则 i 是合数。上面的代码还可以优化。第一是基于每个合数必然有一个质因子,所以我们可以只用质数来筛选,第二是 j 的初始条件可以写成j=i*i,因为比如j=i*k(k<i),那么 j 肯定被k 筛选掉了。第三是可以只用n 之前的质数去筛选。优化之后的时间复杂度比O(NlgN)还要低得多。优化以后的代码如下:

for(int i = 2; i <= n; i++){   is_prime[i] = 1;}for(int i = 2; i * i <= n; i++){   if(is_prime[i])   {         for(int j = i * i; j <= n; j += i)      {         is_prime[j] = 0;      }   }}

原创粉丝点击