int prime[MAXM]; //最大素数个数
bool vis[MAXN>>1]; //打表范围
void prime_table(){
memset(vis,0,sizeof(vis));
int sq=sqrt(MAXN+1); //+1防止误差
prime[0]=2;
num=1;
for(int i=3;i<=sq;i+=2){
if(vis[i>>1]) continue;
for(int j=i*i;j<=MAXN;j+=(i<<1)) vis[j>>1]=1;
}
for(int i=1;i<=(MAXN>>1);i++) if(!vis[i]) prime[num++]=i<<1|1;
}
1.偶数都不算,2特判。把3,5,7,11...的奇数倍都标记不是素数。
2.为什么j从i*i开始?因为i乘以比i小的奇数之前都算过,比如i=5,那么5*3就不用算,因为在3*5的时候算过。
3.为什么i只循环到sq?因为j从i*i开始?若i>sq,则j=i*i>MAXN,不在要求的范围内了。
4.因为是奇数,vis数组只用开一半,标记访问的时候用j>>1代表j,最后判断的时候若vis[i]=1,说明i*2+1是素数。
关于MAXM的取值问题,π(x)表示不超过x的素数个数,π(x)≈x/lnx。
100000以内素数个数:9592
1000000以内素数个数:78498
5000000以内素数个数:348513
10000000以内素数个数:664579
100000000以内素数个数:5761455