埃式筛法
以素数的倍数一定不是素数,在判断一个素数之后将它的倍数都筛掉
const int N = 1e7 ; //1e7约为10M
int pirme[N] ; // 存放素数
bool vis[N] ; // 判断素数是否被筛掉
int init(int n){ //计算2 - n 内的素数
int pos = 0 ;
for (int i = 0 ; i <= n ; ++ i) vis[i] = false ;
for (int i = 2 ; i <= n ; ++ i){
if (!vis[i]) prime[pos++] = i ;
for (int j = 2*i ; j <= n ; j += i) //i的倍数都不是素数,筛掉
vis[j] = true ;
}
return pos ; //返回素数个数
}
欧拉筛法
在埃式筛法中,有可能重复筛掉合数,比如6会被2和3筛掉,在欧拉筛法中,在外层枚举 i ,当i为素数时,在内层循环枚举 j (第j个素数),筛掉 i * prime[j] ,如果i%prime[j] == 0时,相当于i = prime[j] * k (k为一个正整数) ,那么如果后面继续枚举到一个素数prime[m],就要筛去 i*prime[m],也就是prime[j] k prime[m] ,因为我们枚举素数是从小到大的,所以筛去i * prime[m] 的最小质因子应该是prime[j] ,若继续枚举就会出现冗余。例如:当 i=8 时,j = 0,prime[j] = 2 如果不跳出循环prime[j+1] = 3,8 * 3 = 2 * 4 * 3 = 2 * 12,在i = 12时会再次计算。
#include <cstdio>
const int N = 1e8 + 5 ;
int prime[N] , vis[N] ;
int init(int n){
int pos = 0 ;
for (int i = 2 ; i <= n ; ++ i){
if (!vis[i])
vis[i] = 1 , prime[pos++] = i ;
for (int j = 0 ; j < pos ; ++ j){
if (i*prime[j] > n) break ;
vis[i*prime[j]] = 1 ;
if (i%prime[j] == 0) break ;
}
}
return pos ; //返回素数个数
}
int main(){
return 0 ;
}