找质数的优化算法 优化一 原理 2是唯一的偶数质数,先将2输出
其余的质数都是奇数,所有被除数从3开始算,每次加2,遍历所有范围内的奇数
除数从3开始遍历,遍历到被除数的平方(一个数因数都是一个大于等于该数平方,一个小于等于该数平方,成对出现)
例题与代码 题目一
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <cmath> using namespace std;int main () { int N ; cin >> N; if (N>=2 ){ printf ("2\n" ); } for (int i = 3 ; i < N; i += 2 ) { bool flag = true ; int stop = sqrt (i); for (int j = 3 ; j <=stop; j += 2 ) { if (i % j == 0 ) { flag = false ; break ; } } if (flag) printf ("%d\n" , i); } return 0 ; }
题目二
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> using namespace std;int N;int arr[100 ];int main () { cin >> N; int t = 0 ; while (t < N) { cin >> arr[t]; t++; } for (int i = 0 ; i < N; i++) { bool flag = true ; if (arr[i] == 1 ) flag = false ; if (arr[i]!=2 && arr[i]%2 == 0 ) flag = false ; for (int j = 3 ; j <= sqrt (arr[i]); j+=2 ) { if (arr[i] % j == 0 ) { flag = false ; break ; } } if (flag) printf ("%d " , arr[i]); } return 0 ; }
优化二 埃氏筛 原理 如果我们想要知道小于等于 n 有多少个素数呢?
一个自然的想法是我们对于小于等于 n 的每个数进行一次判定。这种暴力的做法显然不能达到最优复杂度,考虑如何优化。
考虑这样一件事情:如果 i 是合数,那么 i 的倍数也一定是合数。利用这个结论,我们可以避免很多次不必要的检测。
如果我们从小到大考虑每个数,然后同时把当前这个数的所有(比自己大的)倍数记为合数,那么运行结束的时候没有被标记的数就是素数了。
时间复杂度 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> using namespace std;const long long int N=100000000 ;long long int is_prime[N];long long int prime[N];int Eratosthenes (long long int n) { long long int p = 0 ; for (long long int i = 0 ; i <= n; ++i) is_prime[i] = 1 ; is_prime[0 ] = is_prime[1 ] = 0 ; for (long long int i = 2 ; i <= n; ++i) { if (is_prime[i]) { prime[p++] = i; for (long long int j = i * i; j <= n;j += i) is_prime[j] = 0 ; } } return p; } int main () { long long int n; cin>>n; for (int i=0 ;i<Eratosthenes (n);i++) printf ("%lld\n" ,prime[i]); return 0 ; }
优化三 欧拉筛 原理 在埃氏筛的基础上优化 ,每次只筛选到(i*(i除了1之外最小公因数的数)
确保不重复筛选
(加一行代码)
时间复杂度 代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> using namespace std;const long long int N=10000000 ;long long int is_prime[N],prime[N];int cnt=0 ;void init (long long int MAXN) { for (long long int i = 2 ; i <= MAXN; i++) { if (!is_prime[i]) { prime[cnt++] = i; } for (long long int j = 0 ; j < cnt; j++) { if ( i * prime[j] > MAXN) break ; is_prime[i * prime[j]] = 1 ; if (i%prime[j]==0 ) break ; } } } int main () { long long int n; cin>>n; init (n); for (int i=0 ;i<cnt;i++) printf ("%lld " ,prime[i]); return 0 ; }
1 if(i%prime[j]==0) break;//关键
参考文献:
线性筛的理解及应用 - Rogn - 博客园 (cnblogs.com)
(21条消息) 线性筛二喵君的博客-CSDN博客 线性筛