四种质数筛选算法总结(c++)

您所在的位置:网站首页 秦国几代君王作为 四种质数筛选算法总结(c++)

四种质数筛选算法总结(c++)

2023-12-04 05:26| 来源: 网络整理| 查看: 265

文章目录 质数筛选枚举法埃氏筛线氏筛奇数筛 参考自: leetcode题解,计数质数

质数筛选

质数:除了1和它本身以外不再有其他因数的自然数。

合数:与质数相反。

枚举法

枚举法是查找质数最容易想到的方法,又被称为试除法。

它的思路就是遍历从2到n这个数的所有的数字,判断这个数字能否被这个序列种的任意一个序列整除,如果整除,则说明它不具有唯一的因子(1和它本身)

代码如下:

int func(int n) { int ans = 0; bool isPrimer; for (int i = 2; i if (i % j == 0) { //如果有任意一个数能够被整除,则说明其一定不是质数,则直接退出 isPrimer = false; break; } } if (isPrimer) //如果是质数,则递增 { ans++; } } return ans; }

枚举优化

观察以下数字的形式:

4: 1 * 4 ,2 * 2 , 4 * 1

5: 1* 5 ,sqrt(5) * sqrt(5) , 5 * 1

6: 1* 6 ,2 * 3 ,sqrt(6) * sqrt(6) ,3 * 2 , 6 * 1

8: 1* 6 ,2 * 4 ,sqrt(8) * sqrt(8) ,4 * 2 , 6 * 1

可以得到,无论数字是质数还是合数,可以认为以中间的两个因子相乘,他们的左右两边是一致的。也就是说,遍历了前面,我们如果继续遍历,则会导致重复的现象出现,则我们完全可以避免他。

优化一个地方:

... for (int j=2;j if (isPrimer[i] == 1) { ans++; if ((long long) i*i isPrimer[j] = 0; } } } } return ans; } 线氏筛

在埃氏筛中,我们存储重复标记元素的情况,我们无法避免它,但是我们利用线氏筛来完全避免这种情况。

根据《算术基本定理》:

算术基本定理: 任何一个大于1的 自然数 N,如果N不为 质数 ,那么N可以 唯一 分解成有限个质数的乘积.

例如:

16是一个合数,16可以 分解为 2 * 2 * 2 *2 是一个唯一的,有限个的质数乘积。

20 是一个合数,20 可以分解为 2 * 2 * 5 也是一个唯一的,有限个的质数的乘积。

因此得到结论:

有限多个质数的乘积 一定是一个合数 ---->质数 * 质数 * 质数 … = 合数

作为因子的每个质数不同,则最终的合数也不同。

临时存储每一个质数,只要后面的数字能够被这些质数整除,则直接结束循环,原因:

当前数 能被 质数数组中的某质数 整除,当前数一定是包含 该质数 的合数

合数拆分时,因子中,会出现 两个相同质数,不能保证合数不同

质数数组中后面质数都比 该质数 大。该质数 * >它的质数 = 合数后面一定会遇到

图例:

首先看数字2,它是质数,然后把这个数字放在质数数组[ 0 ]中,在确保范围的情况下,然后把2 依次乘以质数数组中每一项,得到的数字一定是合数(质数 * 质数 = 合数),由此,得到 4是合数,则标记为非质数 0。再来看数字3,它是质数,放入质数数组 [ 1 ]中,在确保范围的情况下,把3依次乘以质数数组中的每一项,得到6 和 9 因此,这两个数字也一定是合数,标识为 0。再来看数字4,它是合数,因此不用放入质数数组中,在确保范围的情况下,用4乘以质数数组中的每一项,得到 8 ( 4 * 2),你是否以为还是有数字12? 答案是并没有,因为,数字4能被质数数组中的第一项(2)整除,我的理解: 12可以被拆分为 2 * 2 * 3,2和3都在质数数组中出现了,因此就没有必要再利用3 * 4得到 12了,因为4可以由 2 * 2得到,因此直接结束此次循环。数字5,确定 10 和 15 不是质数 …

在这里插入图片描述

//线氏筛 int countPrimes_1(int n) { vector primes; vector isPrime(n, 1); for (int i = 2; i primes.push_back(i); } for (int j = 0; j break; } } } return primes.size(); } 奇数筛

优化后的埃氏筛:

偶数一定不是质数! 因此只遍历每一个奇数就可以奇数 * 偶数 = 偶数,因此不必讨论这种情况。奇数 * 奇数 =奇数,因此只在奇数范围内寻找。 class Solution { public: int countPrimes(int n) { //默认全部为true vector primer(n,1); int res=(n>2)?1:0; int t=0; for (int i=3;i res++; if ((long long)i*i primer[t]=0; } } } } return res; } };


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3