求素數(質數)演算法

6個小石頭發表於2017-05-02

(不想做題了。。。。。整理一些資料吧)

求素數(質數)演算法

如果一個正整數只有兩個因子,1和p,則p為素數

1、根據概念判斷

bool isPrime(int n)
{
    if(n < 2) return false;

    for(int i = 2; i < n; ++i)
        if(n%i == 0) return false;

    return true;
}

#include<stdio.h>
int is_sushu(int x)//是素數就返回1,否則返回0
{
    if(x==1)//1既不是素數也不是合數
        return 0;
    else if(x==2)//2是素數
        return 1;
    else
    {
        for(int i=2; i<=sqrt(x); i++)//sqrt降低時間複雜度
            if(x%i==0)//如果x能被i整除,說明x不是素數
                return 0;
        return 1;//是素數返回1
    }
}

2、去掉偶數的判斷

bool isPrime(int n)
{
    if(n < 2) return false;
    if(n == 2) return true;

    for(int i = 3; i < n; i += 2)
        if(n%i == 0) return false;

    return true;
}

3、進一步減少判斷的範圍  sqrt(n)

bool isPrime(int n)
{
    if(n < 2) return false;
    if(n == 2) return true;

    for(int i = 3; i*i <= n; i += 2)
        if(n%i == 0) return false;

    return true;
}

#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 10000//N的大小可以根據需要變化
int a[N];//利用陣列的下標記錄要判斷的數字
void is_sushu()
{
    memset(a,0,sizeof(a));//對陣列a進行初始化為0,不是素數的標記為1,剩下為0的就是素數了
    a[1]=1;//1既不是素數也不是合數,先標記為0
    for(int i=2; i<=sqrt(N); i++)
    {
        if(a[i]==0)//如果i是素數
        {
            for(int j=2; j*i<=N; j++) //迴圈標記的範圍是i*j<N
            {
                a[i*j]=1;//如果i是素數,那麼i*j肯定不是素數
            }
        }
    }//最終所有非素數都標記為1,素數都標記為0
}

4、打表法求素數模板

prime[0]=prime[1]=1;  
     for(i = 2; i <1000; i++)  
         for(j = i * i; j <1000000; j+= i)  
             prime[j] = 1;  

5、一般線性篩選求素數

void make_prime()  {        
    memset(prime, 1, sizeof(prime));  
    prime[0]=false;       
    prime[1]=false;       
    int N=31700;        
    for (int i=2;  i<N;  i++)           
      if (prime[i]) {            
        primes[++cnt ]=i;       
        for (int k=i*i; k<N; k+=i)          
            prime[k]=false;         
      }        
    return;  
}     

6、快速線性篩選求素數

#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;     
}    

7、推薦

half=SIZE/2;   
int sn = (int) sqrt(SIZE);   
for (i = 0; i < half; i++)   
   p[i] = true;// 初始化全部奇數為素數。p[0]對應3,即p[i]對應2*i+3   
for (i = 0; i < sn; i++) {      
if(p[i])//如果 i+i+3 是素數  
{       
    for(k=i+i+3, j=k*i+k+i; j < half; j+=k)   
    // 篩法起點是 p[i]所對應素數的平方 k^2                                          
    // k^2在 p 中的位置是 k*i+k+i  
    //    下標 i         k*i+k+i  
    //對應數值 k=i+i+3   k^2           
       p[j]=false;   
}   
}   
//素數都存放在 p 陣列中,p[i]=true代表 i+i+2 是素數。  
//舉例,3是素數,按3*3,3*5,3*7...的次序篩選,因為只儲存奇數,所以不用刪3*4,3*6.... 

推薦閱讀:

  1. 列印質數的各種演算法 http://coolshell.cn/articles/3738.html  裡面有個用C++模板實現的,純屬開闊眼界,不怎麼實用。
  2. 檢查素數的正規表示式  http://coolshell.cn/articles/2704.html  數字n用  1111。。1 (n個1)表示

相關文章