素数筛法—时间复杂度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 }

演示结果为:

时间: 2024-07-29 14:46:33

素数筛法—时间复杂度O(n)的相关文章

素数筛法知识点整理

素数的定义:除了1和它本身之外,不能被其他整数整除. 一.判定一个正整数n是否为素数的方法: ①定义法:枚举2~n-1这n-2个正整数,如果它们均不能整除n,则可断定n为素数.代码如下:时间复杂度为O(n),如果n为10^9,就不能用此方法. 1 bool is_prime(int n){ 2 if(n==1)return false; 3 for(int i=2;i<n;++i) 4 if(n%i==0)return false; 5 return true; 6 } ②从2开始枚举到不大于s

素数筛法(Eratosthenes筛法)

介绍 Eratosthenes筛法,又名埃氏筛法,对于求1~n区间内的素数,时间复杂度为n log n,对于10^6^ 以内的数比较合适,再超出此范围的就不建议用该方法了. 筛法的思想特别简单: 对于不超过n的每个非负整数p, 删除2p, 3p, 4p,-, 当处理完所有数之后, 还没有被删除的就是素数. 代码 void init() { int cnt=0; for(int i=0;i <= Max;i++) is_prime[i] = true; is_prime[0]=is_prime[1

素数筛法讲解

首先看一看判断素数的方法,就是看一个数n能否被2~n-1内的数整除,如果能整除就不是素数,反之则是,直接上优化后的代码: 1 bool isprime(int x) 2 { 3 for(int i=2;i<=sqrt(x);i++) 4 { 5 if(x%i==0) 6 return false; 7 } 8 return true; 9 } 对于一些题目,需要判断的素数非常大且多,用这种方法的话时间复杂度是绝不允许的,因此就有了素数筛法,顾名思义,是提前把素数筛选出来,这样之后判断的时候就快了

hdu6069[素数筛法] 2017多校3

/*hdu6069[素数筛法] 2017多校3*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; LL l, r, k; const LL MOD = 998244353LL; int T, n, prime[1100000], primesize; bool isprime[11000000]; void getlist(int listsize) { memset(isprime, 1, sizeof

POJ_3421_X-factor Chains(素数筛法)

X-factor Chains Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5659   Accepted: 1786 Description Given a positive integer X, an X-factor chain of length m is a sequence of integers, 1 = X0, X1, X2, -, Xm = X satisfying Xi < Xi+1 and Xi

HDU 6069 Counting Divisors(区间素数筛法)

题意:...就题面一句话 思路:比赛一看公式,就想到要用到约数个数定理 约数个数定理就是: 对于一个大于1正整数n可以分解质因数: 则n的正约数的个数就是 对于n^k其实就是每个因子的个数乘了一个K 然后现在就变成了求每个数的每个质因子有多少个,但是比赛的时候只想到sqrt(n)的分解方法,总复杂度爆炸,就一直没过去,然后赛后看官方题解感觉好妙啊! 通过类似素数筛法的方式,把L - R的质因子给分解,就可以在O(nlogn)的时间之内把所以的数给筛出来. 代码: /** @xigua */ #i

poj 2478 Farey Sequence(基于素数筛法求欧拉函数)

http://poj.org/problem?id=2478 求欧拉函数的模板. 初涉欧拉函数,先学一学它基本的性质. 1.欧拉函数是求小于n且和n互质(包括1)的正整数的个数.记为φ(n). 2.欧拉定理:若a与n互质,那么有a^φ(n) ≡ 1(mod n),经常用于求幂的模. 3.若p是一个质数,那么φ(p) = p-1,注意φ(1) = 1. 4.欧拉函数是积性函数: 若m与n互质,那么φ(nm) = φ(n) * φ(m). 若n = p^k且p为质数,那么φ(n) = p^k - p

NowCoder猜想(素数筛法+位压缩)

在期末被各科的大作业碾压快要窒息之际,百忙之中抽空上牛客网逛了逛,无意中发现一道好题,NowCoder猜想,题意很明显,就是个简单的素数筛法,但竟然超内存了,我晕(+﹏+)~  明明有 3 万多 k 的空间限制……于是我不打表,试了试最暴力的做法,赤裸裸的做法果然超时了,无奈,只好对素数筛法进行位压缩了,这是我目前所能想到的方法了,第一次用上这样的特技,还是调了好一会(位数组里不能用 bool 来定义,具体的话好像 bool 和 int 之类的整型稍有不同:也不能用 int,因其最高位是正负标志

【POJ3006】Dirichlet&#39;s Theorem on Arithmetic Progressions(素数筛法)

简单的暴力筛法就可. 1 #include <iostream> 2 #include <cstring> 3 #include <cmath> 4 #include <cctype> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <numeric> 9 using namespace std; 10 11 co