素数筛选及优化
来源:互联网 发布:access连接sql server 编辑:程序博客网 时间:2024/05/18 03:02
素数的埃式筛选法的思想:对于不超过N的每个正整数,删除2的倍数,3的倍数,4的倍数……N-1的倍数,当处理完所有数之后,还没有被删除的就是素数。
void GetPrime(int N) //从0到N筛选素数{ memset(vis,0,sizeof(vis)); for(int i=2;i<=N;i++) { for(int j=i*2;j<=N;j+=i)//对N以内的倍数处理 { vis[j]=1; //置为合数 } } vis[0]=vis[1]=1;}
这里介绍一个唯一分解定理:任何一个大于1的自然数 N,如果N不为素数,那么N可以唯一分解成有限个素数的乘积。
优化:
由唯一分解定理可知合数一定是素数的倍数,所以就不用再对它们的倍数进行处理而重复操作了。
所以我们可以在第6行和第7行之间插入:
if(!vis[i])
对一个 i(i>2),i 的2~ i-1倍数之前已经处理,所以只需处理 i 的 i~∞ 的倍数的情况。如果i>sqrt(N),则i*i>N,那么处理的倍数就是没有意义的。故第4行可改为:
for(int i=2;i<=sqrt(N);i++)
想想可不可以再优化?
我们可以打打草稿看一下:
2的倍数:4 6 8 10 12 14 16 18 20……
3的倍数:6 9 12 15 18 ……
5的倍数:10 15 20……
可以发现其中还是有重复操作的情况,3的2倍,5的2倍都是2的倍数,5的三倍都是3的倍数,这些数在处理2的倍数,3的倍数时已经处理过,而我们只需考虑3的3倍,3的4倍……5的5倍,5的6倍……
因此我们可以把第7行代码改为:
for(int j=i*i;j<=N;j+=i)
再加一个数组prime存放素数
这样可以得到一个比较好的算法int prime[N1]; //存放素数的数组bool vis[N1]; //判断是否为素数void GetPrime(int N) //从0到N筛选素数{ int ptot=0; memset(vis,0,sizeof(vis)); memset(prime,0,sizeof(prime)); for(int i=2;i<=N;i++) //为了得到素数数组,要放弃之前的小优化,i应该小于等于N { if(!vis[i]) { prime[ptot++]=i; for(int j=i*i;j<=N;j+=i) { vis[j]=1; //置为合数 } } } vis[0]=vis[1]=1;}
还可不可以再优化?
是的,可以。
欧拉筛选可以做到O(n)的时间复杂度,因为给出的算法已经可以应付大多数的素数题目,这里就不再讨论了。这里给出一个网址,有兴趣的朋友可以研究一下http://www.cnblogs.com/zyf0163/p/4734985.html
其实还有一种厉(wu)害(lai)的方法:
事先写一个程序对一亿以内的素数打表,输出素数文本,然后把它们放在解题代码的数组里,到时直接查表,即使你不会什么算法,也可以这样做。
其实还有一种厉(wu)害(lai)的方法:
事先写一个程序对一亿以内的素数打表,输出素数文本,然后把它们放在解题代码的数组里,到时直接查表,即使你不会什么算法,也可以这样做。
阅读全文
0 0
- 素数筛选及优化
- 素数筛选 及 最小公倍数
- WV.51-素数筛选优化
- 素数筛选以及优化分析
- 素数筛选法-Eratosthenes筛法优化
- 求对数及筛选法求素数
- 素数及素数筛选算法训练基础题(一)
- 素数筛选
- 筛选素数
- 素数筛选
- 筛选素数
- 素数筛选
- 筛选素数
- 素数筛选
- 素数筛选
- 筛选素数
- 素数筛选
- 素数筛选
- 《大话数据结构》学习笔记--chapter 5
- 求取两个数的最大公约数
- 单列模式读取properties配置文件
- 第二章Hello World-跟赵大笨笨学SpringMVC
- java处理百度编辑器ueditor上传的图片等多媒体文件
- 素数筛选及优化
- 遍历二叉树
- [深度探索C++对象模型]trival constructor和non-trival constructor
- JVM G1收集器
- Python单例模式父类
- 使用vue路由做出一个可以切换的demo
- Android NDK编译librtmp 三重奏 -- (一)编译zlib
- Leetcode 104. Maximum Depth of Binary Tree
- Python爬朋友圈好友信息