使用厄拉多塞筛法计算素数的和

本文介绍了一种利用厄拉多塞筛法优化计算N以内所有素数和的过程,通过避免逐个判断每个自然数是否为素数,大大提高了计算效率。通过代码实现展示了算法的具体应用,并对比了不同规模N下算法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求N以内所有素数的和,最普通的方法是对N以内所有自然数进行一次是否为素数的判断,然后将所有素数相加。

然而对某个自然数s是否为素数的判断是相当费时间的,需要判断其是否可以整除0到s^0.5之间的所有自然数,如果s很大的话,这将相当耗时。

两千多年前的数学家厄拉多塞提出的厄拉多塞筛法可以一定程度上减少计算素数和时的工作量。

维基百科上埃拉托斯特尼筛法词条中有一个很直观的示意图,如下:


例如现在要求自然数N以内所有素数的和,那么此筛法的基本方法是从2开始,把2作为素数,然后把N以内的所有2的倍数全部除去。此时下一个数字为3,将3作为素数,然后把N以内的所有3的倍数全部除去。下一个数字是5,把5作为素数,然后把N以内的所有5的倍数全部除去……一直这样下去,直到N^0.5,此时剩下的没有被除去的数全都是素数,把这些数和之前的所有素数相加即可得到结果。

这样的话,省掉了很复杂的判断某自然数是否为素数的过程。在N很大的时候,效率是秒杀开头提到的普通方法的。

代码如下:

#include "TimerCounter.h"
#include "TimerCounter.cpp"
#include <iostream>

using namespace std;

int main()
{
    uint64_t MAX;
    while(cin>>MAX)
    {
        TimerCounter tc;
        tc.Start();
//计时开始

        bool *isprime=new bool[MAX];
	//创建一个大小为MAX的bool类型数组
        uint64_t primeSum=0;
	//创建一个uint64_t类型的变量用来存储素数的和
        memset(isprime, true, MAX);
	//使用memset填充bool类型数组
        for(uint64_t i = 2; i * i < MAX; ++i) 
        {
            if(isprime[i])
            {
                for(uint64_t j = i * i; j < MAX; j += i)
                    isprime[j] = false;
            }
        }
        for(uint64_t i = 2; i < MAX; ++i)
        {
            if(isprime[i])
                primeSum+=i;
        }
        delete[] isprime;
        tc.Stop();
	//计时结束
        cout<<primeSum<<" ("<<tc.dbTime<<"s)"<<endl;
	//输出素数和,所用时间
    }
    return 0;
}
测试这段代码,截图如下:

输入自然数N,输出N以内的所有素数的和,程序运行时间。

可以看到随着N的大小逐渐增大,时间的增长非常明显,可见该算法还是有一些缺点的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值