素数问题(转)

素数问题(转)
参考文:http://blog.csdn.net/hechenghai/article/details/6733907

定义:除了1和其本身,没有其他约数的数。
算法:用n分别试除2到sqrt(n)的数,如果中间有一个能整除,即为合数,否则即为素数。

著名的素数筛选法:
公元前300多年,学者埃拉托色尼提出了一种方法,他在一张纸上写上自然数列的数字,把它贴在一个柜子上,然后把其中的合数一个一个地挖去。得到一个有许多小孔的像筛子一样的东西,所有的合数都好像被筛子筛去了一样。埃拉托色尼是怎样筛法呢?他若造一张1到50的素数表,首先写上1到50的所有自然数,然后先划去1,把2留下,再划去其他所有2的倍数,把3留下。再划去其他所有3的倍数,把5留下。又划去其他所有5的倍数……以此类推,可以得到50以内的所有素数。
按照埃拉托色尼的筛法,会不会划到最后都是合数呢?也就是素数的个数是不是有限的呢? 约公元前275年,希腊著名的数学家欧几里德用巧妙的方法证明了素数是无限的。

C语言算法
//求1000以内所有素数,用筛选法

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define SIZE 1000
 
int main(int argc, char *argv[])
{
  int sign[SIZE];
  int i, j;
  for (i = 0; i < SIZE; i++){
      sign[i] = 1;
  }
  
  for (i = 2; i <= sqrt((double)SIZE); i++){
      if (sign[i]){
          for (j = 2; j <= SIZE / i; j++){
              sign[i*j]=0;
          }
      }
  }
  
   for (i = 2; i < SIZE; i++){
      if(sign[i])
          printf("%d,",i);
  }
  system("PAUSE");
  return 0;
}

素数判定方法:
1.遍历2以上N的平方根以下的每一个整数,是不是能整除N;(这是最基本的方法)

C语言描述:

int isPrimeNumber(int n){
    int i;
    for (i = 2; i <= sqrt(n); i++){
        if (n % i == 0) return 0;
    }
    return 1;
} 

2.遍历2以上N的平方根以下的每一个素数,是不是能整除N;(这个方法是上面方法的改进,但要求N平方根以下的素数已全部知道)

但以上算法都不适合长整数的素数判断,通常会采用概率算法。(这里就不贴概率算法了。)

bool is_prime(int n)//判断n是否为素数,是素数返回1
{
    int i;
    bool flag = 1;
    for(i = 2; i <= sqrt(n); i++)
    {
        if(n % i == 0){
            flag = 0;
            break;
        }
    }
    return flag;
}

小范围内筛素数(数据不太大):

#define Max 1000
int Prime[500];
int q;
void get_prime()
{
    q = -1;
    Prime[++q] = 2;
    Prime[1] = 3;
    int i;
    for(i = 5; i <= Max; i++){
        for(j = 0;Prime[j]*Prime[j] <= i &&i%Prime[j] != 0; j++);
        if(Prime[j]*Prime[j] > i)Prime[++q] = i;
    }
} 

大范围内筛素数的普通筛法(很慢):

#define Max 1000000
int Prime[500000];
bool IsPrime[Max] = {1};
int q;
void get_prime()
{
    q = -1;
    int i,j;
    for(i = 2; i*i < Max; i++){
        if(IsPrime[i] == 1){
            for(j = i+i; j < Max; j += i){
                IsPrime[j] = 0;
            }
        }
    }
    for(i = 2; i < Max; i++){
        if(IsPrime[i] == 1)
        Prime[++q] = i;
    }
} 

大范围内素数的线性筛法(比普通筛法更快)

#define Max 1000000
int Prime[500000];
bool IsPrime[Max] ;
int q;
void get_prime()
{
    memset(IsPrime,true,sizeof(IsPrime));//将数组初始化为true
    q = -1;
    int i,j;
    for(i = 2; i < Max; i++){
        if(IsPrime[i] == 1)
            Prime[++q] = i;
        for(j = 0;j <= q && Prime[j] * i < Max; j++){
                IsPrime[Prime[j] * i] = 0;
                if(i % Prime[j] == 0)break;
        }
    }
} 

求某一区间(a,b)内的素数

有时候我们碰到的问题是要求求出a b间的素数,而a又比较大,这种情况下就可以用这种方法实现(a>2)
注意:要先通过以上几种方法求出2到sqrt(a的最大取值)范围内的素数存入Prime[].

int prime[500000];
bool isprime[1000000];
int qt;
void get_prime1(int a,int b)
{
    int i,j,k;
    for(i = 0; i <= b - a; i++)
    isprime[i] = 1;
    for(i = 0; Prime[i]*Prime[i] <= b && i <= q;i++){
            k = a/Prime[i];
            if (k*Prime[i] < a) k++;
            if (k <= 1) k++;
            while(k*Prime[i] <= b){
                isprime[k*Prime[i] - a] = 0;
                k++;
            }
    }
    qt = -1;
    for(i = 0; i <= b - a; i++)
    {
        if(isprime[i] == 1)
        prime[++qt] = i + a;
    }
}

posted on 2012-05-21 22:19  在旅途  阅读(448)  评论(0编辑  收藏  举报

导航