【算法-簡單數學問題】- 素數表的獲取(簡單方法和埃式篩法)

素數與素數表基本概念

素數又稱爲質數,是指除了1和本身之外,不能被其他數整除的一類數。注意: 1既不是素數,也不是合數。

直接對於一定範圍內的素數進行判定求取素數表,採用直接簡單遍歷的方式,這樣的時間複雜度爲O(n),那麼如果使用加快的方法可以這樣分析:
如果在2 ~ n-1中存在n的約數,那麼不妨設這個約數爲k,那麼由k*(n/k) ==n可知,n/k也是n的一個約數,並且k與n/k必然一個小於sqrt(n),而另一個大於sqrt(n),通過這樣的思路就可以降低算法的複雜度。

示例代碼:

bool isPrime(int n) {
    if(n <= 1) return false; // 特判
    int sqr = (int)sqrt(1.0 * n);  //求得根號n
    for(int i = 2; i < sqr; i++) {  // 遍歷2~根號n
        if(n % i == 0) return false; // n是i的倍數,則n不是素數
    }
    return true; // n是素數
}

上述代碼照片那個,sort的作用是爲一個浮點數開根號,需要添加math.h頭文件。

由於sqrt的參數要求是浮點數,因此在n前面需要乘上1.0使其變成浮點型。

素數表的獲取

用以上的方法實現素數表的獲取,時間複雜度爲O(n*根號n)
如果出現大範圍素數表需要求解,以上解法將力不從心,所以可以使用各種“篩法”,其中“埃式篩法”是最簡單的一種。

其實“埃式篩法”就是如果我發現了某一個數是一個素數,那麼這個數的所有倍數,都不是素數了,就把這些倍數全部篩掉了。這裏拿一個例題講解:

求正整數M~N之間的所有素數:

算法代碼:

#include <stdio.h>
const int maxn = 1000001;
int prime[maxn], num = 0;
bool p[maxn] = {0};
void Find_Prime (int n) {
    for(int i = 2; i < maxn; i++) {
        if(p[i] == false) {
            prime[num++] = i;
            // 只需要n個素數,因此超時即可結束
            if(num >= n) break;
            for(int j = i + i; j < maxn; j +=i) {
                p[j] = true;// 都不是素數
            }
        }
    }
}

int main() {
    int m, n, count = 0;
    scanf("%d%d", &m, &n);
    Find_Prime(n);
    // 輸出從第m個素數至第n個素數
    for(int i = m; i <= n; i++) {
        // 下標從0開始
        printf("%d",prime[i - 1]);
        count++;
        if(count % 10 != 0 && i < n) printf(" ");
        else printf("\n");
    }
    return 0;
}

這裏需要注意的幾點:

  • 1不是素數
  • 素數表長至少要比n大1
  • 在Find+Prime()函數中要特別留意i < maxn不能寫成i <= maxn
  • main函數中要記得調用Find_Prime(),不然不會出現結果
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章