素数筛

要求1-100000范围内的素数,如果用自定义函数挨个求,对于大范围的求素数会非常耗时。复杂度为O(n * sqrt(n)),所以可以用素数筛法来求大范围内的素数 
说一下原理: 
开一个标记数组,全部初始化为true,0、1不是素数,直接从数组里划掉。 
从2开始,凡是2的倍数、且小于100000的,全部标记为false。 
再找2以后的、是素数的下一位数,是3 
从3开始,凡是3的倍数、且小于100000的,全部标记为false。 
再找3以后的、是素数的下一位数,是5 
从5开始,凡是5的倍数、且小于100000的,全部标记为false。 
这样循环,直到开始的位置大于100000,退出循环。 
这样,所有标记为TRUE的元素的下标全是素数。 
贴上代码

bool isprime[1000010];
    memset(isprime, true, sizeof(isprime));
    for (int i = 2; i <= 1000; i++)
    {
        if (isprime[i])
            for (long long j = 2; j * i <= 1000; j++)
                isprime[j * i] = false;
    }
  • 然而这样做会有重复的标记为 false 的过程,想要提高效率,还可以采用下面这种办法,在对大数据处理的时候会有明显的优势
    bool isprime[1010];
    memset(isprime, true, sizeof(isprime));
    for (int i = 2; i <= 1000; i++)
    {
        if (isprime[i])
            for (long long j = 2; j * i <= 1000; j++)
                isprime[j * i] = false;
    }

解释一下 for (i = j * j; i <= 1000000; i += j + j) 这个循环 
首先从 i + = j + j 说起: 
首先在上面已经把所有的偶数位全部标记为 false,所以,当 a[j] 能进入在这个 for 循环上面if的时候,j 一定是个奇数。i 的起始值是 j * j 所以,起始值也一定是个奇数。 
所以i一下加两个 j ,因为加上一个j后一定是个偶数。 
在说起始值为什么为 j * j : 
像上面所说,j是个奇数。 
对于 j * (j - 1) ,因为j - 1是个偶数,所以 j * (j - 1) 一定是个偶数,其所在位置一定标为false 。 
对于j * (j - 2k) (k = 1, 2, 3…)j - 2k 一定是个奇数,对于任意的j * (j - 2k),一定有这样一个循环标记过j * (j - 2k):for(i=(j-2k) * (j - 2k); i <= 1000000; i += j + j),所以j * (j - 2k)一定是一个确定了的位置 
PS:注意第二层循环要用 long long ,因为 i * i 可能会产生一个大于 int 类型的数,这时候用 int 类型变量接收会产生段错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值