素数筛法

求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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值