几种素数筛法

  素数的求解是数论题目中频繁遇到的问题,下面介绍几种求 n 以内的素数的算法

全局定义:

1 const int n = ?;        //n范围
2 const int ma = ?;        //素数个数
3 bool nu[n];            //标记数组
4 int phi[ma];            //存素数
5         

 

1、较为高效的筛法

  思想:从 2 开始,即标记数组为0(或为1),当标记数组为 0(或1) 时,该数为素数,把素数的倍数筛掉。此算法缺陷在于会重复筛选有不同素数因子的合数(比如说6,被2筛一次,又被3筛一次)

代码:

 1 void prime1()            //因为标记的时候会出现大量重复
 2 {
 3     memset(nu, 0, sizeof(nu));
 4     int k = 0;
 5     for(int i = 2; i < n; ++i)
 6         if(!nu[i])
 7         {
 8             phi[k++] = i;
 9             for(int j = i*i; j < n; j += i)
10                 nu[j] = 1;
11         }
12 }

2、线性筛法

  线性筛法就是为了避免重复筛掉同一个合数。思想是:从2 开始遍历,遇到素数就记录下来,当 i 遍历到为前面已经存储的素数的倍数的时候,就跳出循环,这样不仅可以筛选出所有素数,而且避免了重复。

代码:

 1 void prime2()        //线性筛法
 2 {
 3     memset(nu, 0, sizeof(nu));
 4     int k = 0;
 5     for(int i = 2; i < n; ++i)
 6     {
 7         if(!nu[i])    phi[k++] = i;
 8         for(int j = 0; (j<k && i*phi[j]<n ); ++j)
 9         {
10             nu[i*phi[j]] = 1;
11             if(i%phi[j] == 0)    break;
12         }
13     }
14 }

优化:

优化原理:除了2以外,所有素数都是奇数,所以排除2以后,i 就可以不管偶数了,值得注意的是,排除 2 之后,nu[4] 要清除标记。

代码:

 1 void prime3()    //线性筛法改良
 2 {
 3     memset(nu, 0, sizeof(nu));
 4     int  k = 1;
 5     phi[0] = 2, nu[4] = 1;
 6     for(int i = 3; i < n; i += 2)
 7     {
 8         if(!nu[i])    phi[k++] = i;
 9         for(int j = 0; (j<k && i*phi[j]<n); ++j)
10         {
11             nu[i*phi[j]] = 1;
12             if(i%phi[j] == 0)    break;
13         }
14     }
15 }

 

转载于:https://www.cnblogs.com/Duahanlang/p/3212323.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值