請你想出一個算法求出n以內(含n)的所有素數,要求算法的時間復雜度越小越好。
這里介紹一種算法——快速線性素數篩法(歐拉篩法),時間復雜度O(n)。
訣竅在於:篩除合數時,保證每個合數只會被它的最小質因數篩去。因此每個數只會被標記一次,所以算法時間復雜度為O(n)。
具體請看下面的代碼,主要函數是Prime(n)。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 vector<int> Prime(int n) { // 求解n以內(含n)的素數 6 bool flag[n + 1]; // 標記數組,flag[i]==0表示i為素數,flag[i]==1表示i為合數 7 memset(flag, 0, sizeof(flag)); 8 vector<int> prime; 9 int cnt = 0; // 素數個數 10 for (int i = 2; i <= n; ++i) { 11 if (!flag[i]) { 12 prime.push_back(i); // 將i加入素數表 13 cnt++; 14 } 15 for (int j = 0; j < cnt; ++j) { // 保證每個合數只會被它的最小質因數篩去 16 if (i * prime[j] > n) break; 17 flag[i * prime[j]] = 1; 18 if (i % prime[j] == 0) break; 19 } 20 } 21 return prime; 22 } 23 int main(int argc, char const *argv[]) 24 { 25 int n; 26 while(1) { 27 printf("請輸入n,將輸出n以內(含n)的素數:"); 28 scanf("%d", &n); 29 if(n < 0) break; 30 vector<int> prime = Prime(n); 31 int cnt = prime.size(); 32 printf("一共有%d個素數:\n", cnt); 33 for(int i = 0; i < cnt; i++) { 34 printf("%3d ", prime[i]); 35 if(i % 10 == 9) puts(""); 36 } 37 puts("\n"); 38 } 39 return 0; 40 }

演示結果為:

