质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。
根据素数的定义而每个数都进行一次 2 到 ( i − 1 ) 2到(i-1) 2到(i−1)的 M o d Mod Mod,如果被整除则不是质数。
bool Prime(int a){
for(int i=2;i<a;i++){
if(a%i==0){
return false;
}
}
return true;
}
这个朴素判断质数中还可以进行优化,使代码的时间复杂度减少很多。
对于每个小于 根 号 i 根号i 根号i的因数,一定有一个大于 根 号 i 根号i 根号i的因数与之配对,使得两个数的积为 i i i,因此,在我们枚举 i i i的因数时,只需要枚举 < = 根 号 i <=根号i <=根号i的值即可。
bool Prime(int a){
for(int i=2;i<=sqrt(a);i++){
if(a%i==0){
return false;
}
}
return true;
}
好戏真正开始
总而言之,就如下图一般,只要发现 f l a g [ i ] ! = t r u e flag[i]!=true flag[i]!=true,就将它的倍数全部置为 t r u e true true。
const int M=10005;
bool flag[M];
int pre[M];//用这个数组来保存1~n的所有质数
void Prime_Ai(int n){
int k=0;
for(int i=2;i<=n;i++){
if(!flag[i]){
k++;
pre[k]=i;
for(int j=i*2;j<n;j+=i){
flag[j]=true;
}
}
}
}
简而言之,就是避免重复置为 t r u e true true而增加时间复杂度,所以有了线筛。
线筛就是利用 p r e [ M ] pre[M] pre[M]里的质数来避免上述问题。
const int M=1005;
bool flag[M];
int pre[M];
void Prime_xian(int n){
int k=0;
for(int i=2;i<=n;i++){
if(!flag[i]){
pre[++k]=i;
}
for(int j=1;j<=k&&pre[j]*i<=n;j++){
flag[pre[j]*i]=1;
if(i%pre[j]==0)
break;
}
}
}