線性篩素數詳解

一、簡介

線性篩素數,顧名思義,是一種用線性時間複雜度求出所有素數的方法。相比於其他素數篩法,線性篩素數更加高效,因此在實際應用中經常被使用。

二、原理

線性篩素數的核心思想是將每個數都標記為“素數”或“合數”,並在記錄同時篩選掉它的所有倍數,這使其無需對每個數都判斷是否是素數。

三、實現

首先,需要創建一個長度為n+1的數組isPrime,用來標記每個數是否為素數

bool isPrime[MAX_N + 1];  // MAX_N為所求最大值

一開始,將isPrime數組置為true,表示假設所有數都為素數。

for (int i = 2; i <= MAX_N; i++) {
    if (isPrime[i]) {  // 若i為素數
        prime[++cnt] = i;  // 將其加入素數數組中
    }

    for (int j = 1; j <= cnt && i * prime[j] <= MAX_N; j++) {
        isPrime[i * prime[j]] = false;  // 篩去合數
        if (i % prime[j] == 0) {  // 優化2
            break;
        }
    }
}

其中,主循環枚舉i從2到n,若i為素數,則將它加入素數數組中,並遍歷它的所有倍數j,將它們標記為合數。在遍歷的過程中,若發現當前數i是某個素數的倍數,那麼就停止遍歷i的倍數,因為它已經被篩選掉了。

四、優化

在實際應用中,線性篩素數還有一些優化操作,可以進一步提高效率。

1、使用已有的素數數組

仔細觀察上述代碼可以發現,每次篩選合數時都要遍歷已經求得的素數數組。這乍一看,效率還不如普通的試除法,但是其時間複雜度是線性的,實際效率也很高。但是,我們可以想到一個優化,那就是直接使用已經求得的素數來篩選。

for (int j = 1; j <= cnt && i * prime[j] <= MAX_N; j++) {
    isPrime[i * prime[j]] = false;
    if (i % prime[j] == 0) {
        break;
    }
}

通過使用已有的素數數組,在篩選的過程中,不僅效率提高了,同時也減少了計算量。

2、拆分判斷

接着,我們可以注意到,在上述代碼中,除數同為質數時,同樣的操作被執行了多次。比如,當i是2的倍數時,就需要將2從它的所有倍數中篩掉;當i是3的倍數時,需要將3從它的所有倍數中篩掉。在這種情況下,代碼中會重複調用,算法效率會受到影響。那麼是否可以做一些調整,提高執行效率呢?答案是肯定的,在這裡我們可以把這些操作拆分開來,以減少重複操作。

for (int j = 1; j <= cnt && i * prime[j] <= MAX_N; j++) {
    isPrime[i * prime[j]] = false;
    if (i % prime[j] == 0) {
        break;
    }
}

3、減少判斷次數

最後,我們需要注意到,當我們在判斷某個數是否為素數時,實際上只需要判斷它是否是當前素數數組中所有素數的倍數就可以了。顯然,這個數可不是所有數的倍數,因此,以它為起點遞增的倍數也不可能是所有數的倍數,只有遞增素數的倍數能夠被篩掉。基於此,我們可以減少判斷次數。

for (int j = 1; j <= cnt && i * prime[j] <= MAX_N; j++) {
    isPrime[i * prime[j]] = false;
    if (i % prime[j] == 0) {
        break;
    }
}

五、總結

線性篩素數是一種高效的素數判定方法,通過將每個數都標記為“素數”或“合數”,並在記錄同時篩選掉它的所有倍數,實現了無需對每個數都判斷是否是素數。在實際應用中,可以通過使用已有的素數數組、拆分判斷和減少判斷次數等方式,進一步提高算法效率。

六、完整代碼

const int MAX_N = 1000000;

bool isPrime[MAX_N + 1];
int prime[MAX_N + 1];
int cnt = 0;

void linearSieve() {
    for (int i = 2; i <= MAX_N; i++) {
        if (isPrime[i]) {
            prime[++cnt] = i;
        }

        for (int j = 1; j <= cnt && i * prime[j] <= MAX_N; j++) {
            isPrime[i * prime[j]] = false;
            if (i % prime[j] == 0) {
                break;
            }
        }
    }
}

int main() {
    memset(isPrime, true, sizeof(isPrime));
    linearSieve();

    for (int i = 1; i <= cnt; i++) {
        printf("%d\n", prime[i]);
    }

    return 0;
}

原創文章,作者:CSGTF,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/331836.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
CSGTF的頭像CSGTF
上一篇 2025-01-20 14:10
下一篇 2025-01-20 14:11

相關推薦

  • 用不同的方法求素數

    素數是指只能被1和自身整除的正整數,如2、3、5、7、11、13等。素數在密碼學、計算機科學、數學、物理等領域都有着廣泛的應用。本文將介紹幾種常見的求素數的方法,包括暴力枚舉法、埃…

    編程 2025-04-29
  • Python實現一元線性回歸模型

    本文將從多個方面詳細闡述Python實現一元線性回歸模型的代碼。如果你對線性回歸模型有一些了解,對Python語言也有所掌握,那麼本文將對你有所幫助。在開始介紹具體代碼前,讓我們先…

    編程 2025-04-29
  • 如何輸出100到200之間的素數?

    輸出100到200之間的素數是一個常見的問題,這裡將介紹一種偽代碼實現。 一、素數的定義 素數是只能被1和本身整除的整數。比如2、3、5、7、11等都是素數,而4、6、8、9等就不…

    編程 2025-04-28
  • Python實現100以內判斷素數

    素數,又稱質數,是指在大於1的自然數中,除了1和它本身以外,不能被其他自然數整除的數。在計算機編程中,判斷一個數是否為素數一直是一個經典的問題,本文將介紹如何使用Python實現1…

    編程 2025-04-28
  • 用Python編寫素數程序

    對於很多編程工程師來說,素數是一個常見問題,因為它涉及到了質數、算法和優化等多個方面。Python提供了方便高效的方法來判斷一個數是否為素數。下面我們將從多個方面詳細闡述素數Pyt…

    編程 2025-04-28
  • Python素數判定模塊

    由於素數在計算機安全和密碼學中的重要性,Python作為一門流行的編程語言,自然也提供了許多簡便的方式來判斷一個數是否為素數。本文就將從多個方面來闡述Python定義素數判定模塊。…

    編程 2025-04-27
  • 輸出200以內的素數

    本文將從算法原理、代碼實現、優化等方面詳細闡述如何輸出200以內的素數。 一、算法原理 求解素數的算法有許多,比如試除法、埃氏篩法、歐拉篩法等。這裡我們介紹一種簡單易懂的算法——試…

    編程 2025-04-27
  • Python線性插值法:用數學建模實現精確預測

    本文將會詳細介紹Python線性插值法的實現方式和應用場景。 一、插值法概述 插值法是基於已知數據點得出缺失數據點的一種方法。它常用於科學計算中的函數逼近,是一種基礎的數學建模技術…

    編程 2025-04-27
  • 素數條件Python

    本文將對素數條件Python進行詳細闡述,介紹其概念、優缺點及應用場景。 一、概念 素數條件Python是一種基於Python語言的編程模式,其特點在於對於給定自然數$x$,判斷其…

    編程 2025-04-27
  • Python編程入門:找出1~100的素數

    素數指除了1和本身之外沒有其他約數的自然數。本文將介紹如何使用Python編程找出1~100之間的素數。 一、素數定義及判斷方法 素數是指只有1和本身兩個約數的自然數,因此判斷一個…

    編程 2025-04-27

發表回復

登錄後才能評論