1. 程式人生 > >數論初步之素數判斷

數論初步之素數判斷

eight 有一個 text 大於 strong 復雜 size 是否 class

基本數論-素數判斷

一、暴力求解

  1、一個共識

   x = a*b且x = sqrt(x)*sqrt(x) => a==b==sqrt(x)或者a<sqrt(x) 且 b > sqrt(x),即要麽a==b要麽一個大於根號x一個小於根號x

   且a = x/b,那麽我們只用判斷小於sqrt(x)的數是否可以整除x即可。         

  2、暴力求法(O(n^(2/3)))

                

bool isPrime(int x){ for(int i=2;i<=sqrt(x);i++){ if(x%i==0) return false;
} return true; }
void getPrime(int x){ for(int i=1;i<=x;i++){ if(isPrime(i)) cout<<i; } }

  3、素數普通篩選(n*log(n))

    思想:任何一個素x = 素數*一個數,那麽我們可以在找到一個素數的時候,再花n/i的時間去把現在可以確定不是素數的數給標記出來。

    如:已知2是一個素數那麽:2,4,6,8,10,12...2*i都不是素數。

    那麽時間復雜度為:n/2+n/3+n/5+......+n/p,p為小於n的素數那麽漸進時間復雜度為O(n*log(n))

void getPrime(int x,int* primes){
    for(int i=2;i<=x;i++){
        if(primes[i]==0){
            for(int j=2;j*i<=x;j++)
                primes[j*i] = 1;
        }
    }
}

  4、素數篩選之線性篩選(o(n))

    由3我們可以知道,任何一個數字都可以有一個素數乘一個數得到。比如2是素數那麽4,6,8,10,12,14,16....2*i都不是素數了,比如3是素數那麽6,9,12,15...3*i都不是素數了,我們

    可以看出在我們標記不是素數的時候6,12等在2中標記過,在3中也被標記過這樣一來就多了很多重復的操作,那麽怎麽去優化呢?

    我們最容易想到的就是在int j這個循環中加入,prime[j*i]!=1這個標誌,就可以很容易的跳過多余的標記,那麽我們總共標記了n個元素所以時間復雜度為O(N).

    

void getPrimeLine(int x,int* primes){
    for(int i=2;i<=x;i++){
        if(primes[i]==0){
            for(int j=2;j*i<=x&&primes[j*i]!=1;j++)
                primes[j*i] = 1;
        }
    }
}

   或者我們可以根據當前的已知的素數來標記如已知 1,2,3,5現在第6次標記就用1,2,3,5分別乘2,3,4,5,6這樣每次乘出來的也不一樣最終也不會重復標記,因而時間復雜度為O(N)

  

數論初步之素數判斷