使用欧拉筛法求素数和

上一次写到了厄拉多塞筛法,说到厄拉多塞筛法随着计算上限的成倍增加,计算时间也会成倍增加。

这次的欧拉筛法在时间这方面会比厄拉多塞筛法好很多。

先上代码:

#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <stdint.h>

#define MAX 1000000

int main()
{
	uint64_t* prime;
	prime = (uint64_t*)malloc(MAX*sizeof(uint64_t));
	memset(prime, 0, MAX);
	bool isprime[MAX];
	memset(isprime, true, sizeof(isprime));

	uint64_t index = 0;
	
	for (uint64_t i = 2; i < MAX; ++i)
	{
		if (isprime[i])
		{
			prime[index] = i;
			++index;
		}
		for (uint64_t j = 0; j < index && i * prime[j] < MAX; ++j)
		{
			isprime[i*prime[j]] = false;
			if (i % prime[j] == 0)
			{
				break;
			}
		}
	}
	uint64_t sum = 0;
	for (uint64_t i = 0; i < index; ++i){
		sum += prime[i];
	}
	printf("%llu\n", sum);
	free(prime);

	return 0;
}
欧拉筛法的思路和厄拉多塞筛法很像,素数的倍数标记成合数,但是标记的方法有区别。

欧拉筛法把数字i和已知的所有素数相乘,然后把结果标记为合数。

重要的是计算i%prime[j]是否为0,如果为0则break掉现在的循环。

这一步的意思是,每一个合数只被它最小的素数因数排除一次。

比如说12,12的第一次可能被排除的情况是i=4,此时经过for循环以后,因为4*prime[0]=8,所以首先把8给排除掉,然后因为4可以整除prime[0]也就是2,所以break掉for循环,也就是没有排除掉12.

实际上12会在6的时候被排除,此时6在排除过12以后,break掉for循环,不会排除18,因为18是需要9来排除的。

这样在厄拉多塞筛法中重复被排除的12,18之类的数字就不会被重复排除,算法的效率也就得到了提高。

但是我在想要把MAX设置为十亿,跟厄拉多塞筛法做一个比拼时,发现了一个问题,就是欧拉筛法需要一个数组来保存目前已知的所有素数。

但是即使我已经用了malloc,但是还是不能分配到这么大的内存,直接StackOverflow了。


所以先把算法的实现方法写在这里,等我Google到方法后再修改。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值