素數與素數表基本概念
素數又稱爲質數,是指除了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(),不然不會出現結果