需要知道的前提:
- 合数=最小质因数*最大因数(非自己)
- 所有合数都能分解成质数积
- 如果要从1-n每个数分别判断一次是否是质数,不如让质数的倍数(<n)全部标记为非质数
代码与注释
#include <iostream>
#include <bits/stdc++.h>
#include <math.h>
using namespace std;
const int N=20210605;
//N太大声明必须写外面,不然在main里爆栈
//prime数组记录质数
int prime[N];
//st数组为1代表非质数,默认所有都是质数(0)
bool st[N];
int main() {
int cnt=0;
for(int i=2; i<N; i++) {
//因为质数是从小到大遍历的,所以不用怕后面出现一个合数,但其st值为0
//甚至能省去质数判断的过程
if(!st[i])
prime[cnt++]=i;
for(int j=0; prime[j]<=N/i; j++) {//
st[prime[j]*i]=true;
// 若i%prime[j]==0,由于质因数是从小到大遍历的,此时prime[j]是i的最小质因数,那prime[j]也是i*prime[j+1]这个数的最小质因数,因为i*prime[j+1]=(k*prime[j])*prime[j+1],此时prime[j]<prime[j+1]
//举个例子i=4,prime[j]=2时,筛选8,但在i=4,prime[j+1]=3时,12会被筛选,而12应该在之后i=6,prime[j]=2时筛选,却因为prime[j]=2在这一轮因为时12最小质因数就筛选了。
if(i%prime[j]==0)break;
}
}
cout<<ans;
return 0;
}