质数筛选--快速筛选出小于等于N的质数
来源:互联网 发布:程序员视频教程 编辑:程序博客网 时间:2024/05/17 06:09
Eratosthenes筛法(O(nlog^logn) )
此方法非常的简单:
1. 维护一个数组vector<bool> prime(n + 1, true)
既让数组中的所有数都为真,表明它是质数。
2. 对于每一个质数,删除它的倍数,因为质数的倍数一定是合数。让后将数组中对应的数改为false,这样就可以避免遍历他。
代码如下:
int findPrime(int n) { vector<bool> prime(n + 1, true); int res=0; for (int i = 2; i <= n; i++) { if (prime[i]) { //判断其是否是素数 for (int j = 2; j*i <= n; j++) //删除所有该素数的倍数 prime[j*i] = false; res++; } } return res;}
上述的筛选速度已经是很快了,但是他有一个问题。比如合数10,在枚举2的时候我们判定了一次,在枚举5的时候我们又判定了一次。因此使得其时间复杂度比O(n)要高
Eular质数筛法
与Eratosthenes筛法不同的是,对于外层枚举i,无论i是质数,还是是合数,我们都会用i的倍数去筛。但在枚举的时候,我们只枚举i的质数倍。比如2i,3i,5i,…,而不去枚举4i,6i…,原因我们后面会讲到。
此外,在从小到大依次枚举质数p来计算i的倍数时,我们还需要检查i是否能够整除p。若i能够整除p,则停止枚举。
利用该算法,可以保证每个合数只会被枚举到一次。我们可以证明如下命题:
假设一个合数k=M*p1,p1为其最小的质因子。则k只会在i=M,primeList[j]=p1时被筛掉一次。
首先会在i=M,primeList[j]=p1时被筛掉是显然的。因为p1是k的最小质因子,所以i=M的所有质因子也≥p1。于是j循环在枚举到primeList[j]=p1前不会break,从而一定会在i=M,primeList[j]=p1时被筛掉
其次不会在其他时候被筛掉。否则假设k在i=N, primeList[j]=p1时被筛掉了,此时有k=N*p2。由于p1是k最小的质因子,所以p2 > p1,M > N且p|N。则i=N,j枚举到primeList[j]=p1时(没到primeList[j]=p2)就break了。所以不会有其他时候筛掉k。
同时,不枚举合数倍数的原因也在此:对于一个合数k=M*2*3。只有在枚举到i=M*3时,才会计算到k。若我们枚举合数倍数,则可能会在i=M时,通过M*6计算到k,这样也就造成了多次重复计算了。
综上,Eular筛法可以保证每个合数只会被枚举到一次,时间复杂度为O(n)。当N越大时,其相对于Eratosthenes筛法的优势也就越明显。
代码如下:
int findPrime1(int n) { vector<bool> prime(n + 1, true); vector<int> primeList(n+1); int primeCount = 0; for (int i = 2; i <= n; i++) { if (prime[i]) { primeCount++; primeList[primeCount] = i; } for (int j = 1; j <= primeCount; j++) { if (i*primeList[j] > n) break; prime[i*primeList[j]] = false; if (i%primeList[j] == 0) break; } } return primeCount;}
对于两者的时间测试来看,其差别是非常小的:
int main() { clock_t start = clock(); cout << findPrime1(5000000) << endl; clock_t finish = clock(); cout<<(double)(finish - start) / CLOCKS_PER_SEC<<endl; //11.854s clock_t start2 = clock(); cout << findPrime1(5000000) << endl; clock_t finish2 = clock(); cout << (double)(finish2-start2) / CLOCKS_PER_SEC << endl; //11.81s}
- 质数筛选--快速筛选出小于等于N的质数
- 求小于等于n的质数个数
- 求一亿以内N的质数!筛选法
- 质数筛选
- 筛选质数
- 小于N的质数
- 筛法求小于等于整数n的所有质数
- 动态规划求小于等于n的质数个数
- 求质数的筛选算法
- 用筛选法求N以内的质数
- 小于等于n的素数的个数(埃式筛选法和欧拉筛选)
- Eratosthenes筛选求质数
- 线性筛选质数
- 筛选求质数
- 质数筛选方法
- 筛选法求质数
- 质数/素数 和筛选
- 质数筛选法
- LeetCode(383)Ransom Note
- 【BZOJ2844】albus就是要第一个出场,线性基
- leetcode_389 Find the Difference
- Opencv中的Mat类使用方法总结
- 建议8: 避免给枚举类型的元素提供显式的值
- 质数筛选--快速筛选出小于等于N的质数
- Android0828(二)
- 使用springmvc拦截器进行登录控制
- Java环境变量配置
- struct在C和C++中的区别
- 文章标题
- 几篇不错的文章
- typeof、instanceof和contructor的使用
- ubuntu 启动流程