1. 程式人生 > >Eratosthenes篩選法(埃拉託斯特尼篩法)

Eratosthenes篩選法(埃拉託斯特尼篩法)

                                                      Eratosthenes篩選法

主要用於求素數,時間複雜度為O(nloglogn),比尤拉篩選法要慢,故我一般不用改法。

由於一個合數總是可以分解成若干個質數的乘積,那麼如果把質數的倍數都去掉,那麼剩下的就是質數了.Eratosthenes篩選法的思想特別簡單:對於不超過n的每個非負整數p,刪除2p,3p,4p,...,當處理完所有數之後,還沒有被刪除的就是素數.如果用vis[i]表示i已經被刪除,則篩選法的程式碼可以寫成:

void isprime(int n)///篩選1-n的素數
{
    memset(vis,0,sizeof(vis));
    for(int i = 2; i <= n; i++)
        for(int j = 2 * i; j <= n; j += i)
            vis[j] = 1;
}

儘管程式碼已經相當高效了,但仍然可以進行改進.首先,在"對於不超過n的每個非負數p"中,p可以限定為素數--只需在第二重迴圈前加一個判斷if(!vis[i])即可.另外,內層迴圈也不必從* 2開始--它已經在= 2時被篩選了.改進後代碼如下:

void isprime(int n)///篩選1-n的素數
{
    memset(vis,0,sizeof(vis));
    int m = sqrt(n + 0.5);
    for(int i = 2; i <= m; i++)
    {
        if(!vis[i])
        {
            for(int j = i * i; j <= n; j += i)
                vis[j] = 1;
        }
    }
}

Eratosthenes篩選法雖然效率高,但是Eratosthenes篩選法做了許多無用功,一個數會被篩到好幾次,最後的時間複雜度是O(nloglogn),對於普通素數演算法而言已經非常高效了,但尤拉篩選法的時間複雜度僅僅為O(n).