埃拉托斯特尼素数筛
其主要原理就是从2开始如果一个数时素数,那么这个素数乘任何正整数一定是合数。
这里用一个标记数组记录某一个数是不是素数。
int flag[100005]={1,1};
memset(flag, 0, sizeof(flag));
for(int i=2; i<=sqrt(100005); i++)
if(flag[i]==0)
for(int j=2; i*j<=N; j++)
flag[i*j]=1;
欧拉素数筛
欧拉筛是一种线性筛,它会从2遍历每一个元素,但是标记每个合数只会标记一次,(埃氏筛会标记同一个合数很多次)。原因就在于如果i能够整除现有素数表中最小那个素数的时候,就会跳出循环。由基本算术定理可以知道,每个大于1的数都能够表示成有限个素数相乘的形式,所以一个合数就可以同时被几个素数整除,但是在这里加入了判断条件break,就保证了每个合数只能被能够整除的最小素数和其它数的乘积时取到,即保证了每个被标记数只被标记一次。
比如说当i取到2的时候,加入素数表,标记4为合数,2能被素数表中的2整除,所以break。
当i取到4的时候,素数表里有2和3,24=8,即2是能够整除8的最小素数,把8标记后,由于4能够被2整除所以这时候就break。
如果没有这个break,那么43=12,而12又等于223,所以当i取到6的时候,会有6*2=12,再次标记。
bool flag[10005];
int prime[10005];//素数表
void prime()
{
memset(flag, 0, sizeof(flag));
int pos=1;
flag[0]=1, flag[1]=1;
for (int i=2; i<=n; i++){
if (flag[i]==0)//如果是素数,加入素数表
prime[pos++]=i;
for (int j=1; j<pos && prime[j]*i<=n; j++){
flag[i*prime[j]]=1;
if (i%prime[j]==0)
break;
}
}
}