1.朴素版的筛法 O(nlogn)
题目:httpss://www.acwing.com/problem/content/870/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> #include <algorithm> using namespace std;const int N = 1000010 ;int n;int cnt;bool st[N];void get_prime () { for (int i = 2 ; i <= n; i++) { if (!st[i]) cnt ++; for (int j = i + i; j <= n; j+=i) st[j] = true ; } } int main () { scanf ("%d" , &n); get_prime (); printf ("%d" , cnt); }
2.埃氏筛法 O(nloglogn)
在上面的代码中在每次判断中我们都执行了f o r for f or 循环来筛掉i i i 的倍数, 但是是可以优化的,我们将f o r for f or 循环放进i f if i f 判断里面,这样当i 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 #include <iostream> #include <algorithm> using namespace std;const int N = 1000010 ;int n;int cnt;bool st[N];void get_prime () { for (int i = 2 ; i <= n; i++) { if (!st[i]) { cnt ++; for (int j = i + i; j <= n; j+=i) st[j] = true ; } } } int main () { scanf ("%d" , &n); get_prime (); printf ("%d" , cnt); }
3.线性筛法O(n)
算法思想 :将合数分解为一个最小质数乘以另一个数的形式,即 合数 = 最小质数 * 自然数,然后通过最小质数来判断当前数是否被标记过。
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> #include <algorithm> using namespace std;const int N = 1000010 ;int n;int primes[N];int cnt;bool st[N];void get_prime () { for (int i = 2 ; i <= n; i++) { if (!st[i]) primes[cnt++] = i; for (int j = 0 ; primes[j] <= n / i; j++) { st[i * primes[j]] = true ; if (i%primes[j] == 0 ) break ; } } } int main () { scanf ("%d" , &n); get_prime (); printf ("%d" , cnt); }