Eratosthenes 埃拉托斯特尼筛法
思想就是在从2开始遍历的时候筛去2,3,4等等的倍数,因为这些数都是合数,最后剩下的没有被标记的就是素数
但是这个方法会重复筛去一个数,比如12。2的倍数会筛去,3的倍数也会筛去。
下面插入代码,也比较好理解,看代码就能理解
const int MAXN = 1000000;
void Prime()
{
for (int i=0; i<MAXN; i++) prime[i]=1; //先把每个数都定义为合数
prime[0]=prime[1]=0;
for (int i=2; i<MAXN; i++)
{
if (!prime[i]) continue;
for (int j=i*2; j<MAXN; j+=i) prime[j] = 0; //将i的倍数标记为合数
}
}
以上就是埃斯筛法的思路
但是因为它会重复的筛去一个数,所以其实这种筛法还不是最快的,在比赛中可能会遇到卡这种筛法的情况。
下面介绍另一种筛法
欧拉函数
先插个代码吧
思想还不是弄的很通透
#define MAXN 1000000
int prime[MAXN],v[5*MAXN];
int m=0;//m表示现在筛出m个质数
void primes()
{
for(int i=2;i<MAXN;i++)
{
if(v[i]==0)//如果v[i]为0,说明 i 之前没有被筛到过,i 为质数
{
v[i] = i;
prime[++m] = i;
}
for(int j = 1;j<=m;j++)//遍历小于 i 的所有质数
{
//如果质数大于 i 的最小质因数或者乘起来大于MAXN就跳出循环
if(prime[j] > v[i] || prime[j] > MAXN/i) break;
v[i*prime[j]] = prime[j];//标记 i*prime[j] 的最小质因数是prime[j]
}
}
}