簡明扼要篩法求素數

埃拉特斯特尼篩法(埃氏篩)

原理:

當一個數是素數的時候,那麼他的倍數肯定是合數。時間複雜度爲 O(nloglogn)。

int isprime[MAXN];
int vis[MAXN];
void Prime(int n)
{
    int cnt = 0;
    memset(vis, 0, sizeof(vis));  //vis裏0是素數,1是合數
    vis[0] = 1;
    vis[1] = 1;
    for (int i = 2; i < n; i++){
        if (!vis[i]){
            isprime[cnt++] = i;  //保存素數
            for (int j = i * i; j < n; j += i){
                vis[j] = 1;  //不是素數
            }
        }
    }
}

歐拉篩

原理:

首先,任何合數都能表示成一系列素數的積。然後利用了最小的素數因子,每個合數僅被它的最小素因子篩去正好一次。

時間複雜度爲 O(n)。

int isprime[MAXN]; //保存素數
int vis[MAXN];    //初始化
void eulerSieve(int n)
{
    int cnt = 0;
    memset(vis, 0, sizeof(vis));  //0是素數,1是合數
    for (int i = 2; i < n; i++){
        if (!vis[i])
            isprime[cnt++] = i;
        for (int j = 0; j < cnt && i * isprime[j] < n; j++){
            vis[i * isprime[j]] = 1;
            if (i % isprime[j] == 0)
                break;
        }
    }
}

理解的難點就在於這一句

if (i % isprime[j] == 0) break;

這一句保證每個數只被它的最小質因子被篩一次,

對於一個數 a 假設它可以整除 isprime[ j ],

即 a = isprime[ j ] * x,

那麼 a * isprime[ j + 1 ] = isprime[ j ] * x * isprime[ j+1 ],

所以 j 再往後就沒有必要篩了,

因爲 a * isprime[ j + 1 ] 肯定會在 i = x * isprime[ j + 1 ] 的時候被 isprime[ j ] 篩掉。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章