经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
[算法]浅谈求n范围以内的质数(素数)
来源:cnblogs  作者:李和沛  时间:2018/11/28 9:54:28  对本文有异议

汗颜,数学符号表达今天才学会呀-_-#

下面是百度百科对质数的定义

质数(prime number)又称素数,有无限个。
质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数
求质数的方法自然不少,但主要还是有三大方法,它们运用在不同的领域,根据数据也会变化;

1、傻子求质数法

这种方法十分无脑,任何一个人都能想出来,但这种方法竟然还有几个优化ORZ

时间复杂度是O($N^{2}$);

1.1、无优化版本

  1. 1 void prime()
  2. 2 {
  3. 3 int N = 10000;
  4. 4 int primes[N],pos=0;
  5. 5 register int i,j;
  6. 6 for(i=2;i<N;i++){
  7. 7 bool Flag=0;
  8. 8 for(j=2;j<i;j++)
  9. 9 if(i%j==0)Flag=1;
  10. 10 if(Flag==0)primes[++pos]=i;
  11. 11 }
  12. 12 }

这也是所有求质数中最朴素的求法,自然在平常当中不会使用。

然而有些奇葩题目,求质数的次数很少,就可以用这个啦。↖(^ω^)↗

证明:质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数 ——百度百科。

1.2、n/2 优化版本

  1. 1 void prime()
  2. 2 {
  3. 3 int N = 10000;
  4. 4 int primes[N],pos=0;
  5. 5 register int i,j;
  6. 6 for(i=2;i<N;i++){
  7. 7 bool Flag=0;
  8. 8 for(j=2;j<=i/2;j++)
  9. 9 if(i%j==0)Flag=1;
  10. 10 if(Flag==0)primes[++pos]=i;
  11. 11 }
  12. 12 }

 

这种优化就比上一种快一倍(时间复杂度),但仍然有缺陷,能不能再快一点??_?

证明:x/2以上的数增加就会重复。

1.3、n开平方优化版本

  1. 1 void prime()
  2. 2 {
  3. 3 int N = 10000;
  4. 4 int primes[N],pos=0;
  5. 5 register int i,j;
  6. 6 for(i=2;i<N;i++){
  7. 7 bool Flag=0;
  8. 8 for(j=2;j<=sqrt(n);j++)
  9. 9 if(i%j==0)Flag=1;
  10. 10 if(Flag==0)primes[++pos]=i;
  11. 11 }
  12. 12 }

 这个就是傻子求法的最终版本了,时间复杂度已经优化到了极限(个人认为)。囧rz

证明:因为x=$\sqrt{N}^{2}$的平方,所以sqrt(x)以上的数增加就会重复。

 


 2、埃氏(Eratosthenes)筛法

埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。——百度百科

这种筛法大概是我初一学了快一个学期,开始学质因数时,自己过不了找质数一个题,然后接触的一个算法。

埃氏的筛法思想精华,主要是把质数的倍数剔除,剩下的那些就是质数。+_+

这种算法的时间复杂度是O(nloglogn)。

  1. 1 void prime()
  2. 2 {
  3. 3 int N=10000;
  4. 4 register int i,j;
  5. 5 bool prim[N];
  6. 6 memset(prim,0,sizeof(prim));
  7. 7 prim[1]=1;
  8. 8 for(i=2;i<=sqrt(N);i++)
  9. 9 if(prim[i]==0)
  10. 10 for(j=i+i;j<=N;j+=i)
  11. 11 prim[j]=1;
  12. 12 }

3、欧拉(Euler)筛选法

欧拉筛法就是所谓中的高级筛法,时间复杂度削减到了O($N^{2}$)。

它的思想是在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。

  1. 1 void prime()
  2. 2 {
  3. 3 int N=10000;
  4. 4 int prim[N],bz[N],top=0;
  5. 5 memset(bz,0,sizeof(bz));
  6. 6 register int i,j;
  7. 7 for(i=2;i<=N;i++){
  8. 8 if(!bz[i])prim[++top]=i;
  9. 9 for(j=0;j<=top&&i*prim[j]<=N;j++){
  10. 10 bz[i*prim[j]]=1;
  11. 11 if(i%prim[j]==0)break;
  12. 12 }
  13. 13 }
  14. 14 }

自己还有很多东西都没有学到,不知道什么时候才能脱掉蒟蒻的外套呢。

博主是初中蒟蒻,能力弱,还请大家多多提出改进建议:-D      ——2018.11.27

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号