素数筛法-欧拉筛-个人理解
素数筛选有两种流派,一种是埃氏筛法,一种是欧拉筛,由于埃氏筛法很简单,而且效率没有欧筛效率高。因此本文介绍欧拉筛。
本文用另一种角度讲解为何在if(i%b[j]==0)
时跳出循环,是个人理解,如有不正确的地方欢迎指点
#include<iostream>
using namespace std;
bool a[100001]={1,1};//i=0,i=1的时候都不是质数 ,所以直接标记
int b[100001];//存质数
int k; long long n;
int main()
{
cin>>n;
for(int i=2;i<=100001;i++)//这个意思是在100001里面找到质数并且标记 ,质数最小是2,所以i=2
{
if (a[i]==0) b[++k]=i; //如果没有被标记为1,就是质数。我接下来会讲解为什么是质数。
for(int j=1;j<=k;j++)// //j小于当前所有的质数的个数
{
if(i*b[j]>100001)break;// 如果超出给出的范围,那么就退出循环
a[i*b[j]]=1;//用质数数依次×i,结果标记为合数(也就是标记为1)。
if(i%b[j]==0)break;//最关键的只标记一次
}
}
for(int i=1;i<=n;i++) //你想查询的个数
{int m;
cin>>m;//在100001里面输入你想查询的数
if(a[m]==0)//如果没有被标记,就是质数,直接输出。
{
cout<<m<<' ';
}
}
}
欧拉筛法和埃氏筛法一样,围绕{素数的倍数不是素数}筛选,但是欧拉筛为避免重复筛选,只会通过:最小素因子来消除。
对if(i%b[j]==0)break;
讲解:这时候不妨通过另一种视角,将变量i
在j
循环的内层和外层作用是不一样的,在外层:很好理解,就是循环查看某个数是不是素数。在内存:将i
理解成一个新的变量,它的作用是与b[j]
相乘,从而筛选掉合数,关键是为什么会break
呢?如果i%b[j]==0
,表示i
曾经被b[j]
筛掉的,得赶紧退出,以防后面再被筛掉一次。
这里i%b[j]要跳出循环了,要注意这里的b[j]代表的是第j个素数,注意我们这里的标记是素数的是:i*b[j] 。是第j个素数的i倍,如果不跳出,在后面某一个素数的i倍可能与现在的第j个素数的i倍重复,即后面某一个素数的i倍可能是第j个素数的i倍的倍数,导致重复。
举个例子,假如现在第j个素数是3,i=33,后面某一个素数是11。那么i是素数3的倍数,也是素数11的倍数,如果在33%3==0
时不退出的话,后面到了33%11==0
时它又要在计算一次,重复
欢迎指正!
参考
https://blog.csdn.net/m0_57071296/article/details/119873446
https://blog.csdn.net/gaoqiandr/article/details/126871298
acwing
原文地址:http://www.cnblogs.com/swx123/p/16924773.html
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,请务用于商业用途!
3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员!
8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性