素數篩法—時間復雜度O(n)


請你想出一個算法求出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 }

演示結果為:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM