求1…n素数个数,要求O(n)算法。
对于任意正整数i,我们将其所有的质数(p)倍筛去。
如果当前的p已经是i的约数,那么之后的数p*i中,p一定不是p*i的最小质因子。
每个和数只会被其最小质因子筛去一次。
O(N)
精髓:if此数是素数,一定不会跳出,
else此数的倍数一定被它的质因子筛去了。
因此,可以避免冗余操作。
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e5;
int n,pri[maxn+1];//pri存储素数
bool vis[maxn+1];//vis该数是否被筛去
int euler(int m)
{
int cnt=0;//素数个数
vis[1]=1;//并没有意义
for(int i=2;i<=m;i++)
{
if(!vis[i])//只要还没有被筛去,就是素数
pri[++cnt]=i;
for(int j=1;i*pri[j]<=m&&j<=cnt;j++)
{
vis[i*pri[j]]=1;
if(i%pri[j]==0)//精髓所在
break;
}
}
return cnt;
}
int main()
{
scanf("%d",&n);
printf("%d\n",euler(n));
return 0;
}