Euler筛法介绍

以筛出100以内(含100)的所有素数为例来说明一下欧拉筛法的原理。

和Eratosthenes筛法一样,Euler筛法也从2开始筛,但Eratosthenes筛法会把2的倍数一批全部筛掉,而Euler筛法用2筛时仅仅把2*2(即4)筛掉,而把其它偶数留到后面再筛掉,从而避免了一个偶数被多次筛除带来的性能开销,比如偶数6、8、10,在随后用3、4、5筛的时候会被筛掉。

Euler筛法引入了一个素数队列,从2开始没被筛掉的数会依次加进素数队列,当用3筛时,素数队列里有2和3两个素数,这时会筛掉3*2(即6)和3*3(即9)。

当用4筛时,4因为之前被2筛掉了,所以4不会加进素数队列,此时素数队列里依然只有2和3两个素数,这时会筛掉4*2(即8),但4*3(即12)并不在这时筛掉,这是因为4本身是素数2的倍数,即4*3里不能保证3是最小素因数。

当用5筛时,先把5加入素数队列,随后筛掉5*2(即10)、5*3(即15)和5*5(即25)。

当用6筛时,6因为之前被3筛掉了,所以此时素数队列里依然只有2、3、5,这时会筛掉6*2(即12),但因为判断出6是2的倍数,随后就不会用6进一步去筛掉6*3(即18)。

当用7筛时,先把7加入素数队列,随后依次筛掉7*2(即14)、7*3(即21)、7*5(即35)和7*7(即49)。

当用8筛时,8因为之前被4筛掉了,所以此时素数队列里依然只有2、3、5、7,这时会筛掉8*2(即16),但因为判断出8是2的倍数,随后就不会用8进一步去筛掉8*3(即24)。

当用9筛时,9因为之前被3筛掉了,所以此时素数队列里依然只有2、3、5、7,这时会筛掉9*2(即18)和9*3(即27),但因为判断出9是3的倍数,随后就不会用9进一步去筛掉9*5(即45)。

当用10筛时,10因为之前被5筛掉了,所有此时素数队列里依然是2、3、5、7,这时会筛掉10*2(即20),但因为10是2的倍数,随后不会用10去筛掉10*3(即30)。

当用11筛时,先把11加入素数队列,随后依次筛掉11*2(即22),11*3(即33),11*5(即55),11*7(即77)。11*11(即121)因为大于100而不在筛查范围。

用12筛,只会筛去12*2。

用13筛,13进素数队列,随后依次筛去13*2,13*3,13*5,13*7。13*11不在筛查范围。

用14、15、16筛,依次会筛去14*2、15*2和15*3、16*2。

用17筛,17进素数队列,随后依次筛去17*2、17*3、17*5。17*7不在筛查范围。

……

用49筛,会筛去49*2。49*3不在筛查范围。

用50筛,会筛去50*2。50*3不在筛查范围。

用51筛,不会筛去任何数,因为51*2>100。

随后用52、53、……、99、100筛的过程里,都不再会筛去任何数,而只有素数进素数队列的行为。

由上述过程可知,欧拉筛法的核心思路是:对于筛查范围内的任意一个合数m,只使用m中除m之外最大的因数把m筛去。例如,45=3*3*5,确保用15筛去45即可。更一般的情形,m=p1*p2*……*ps,其中p1、p2、……、ps均为素数且满足p1<=p2<=……<=ps,则确保用p2*……*ps筛去m即可。

Euler筛法的C++程序实现

宏定义和全局量定义

1 typedef unsigned char u8;
2 typedef unsigned long ulong;
3 static ulong s_last = 0;
4 static u8* s_pAll = NULL;
5 static std::vector<ulong> s_vecPrime;

和Eratosthenes筛法实现的定义完全一样。

main函数实现

 1 int main()
2 {
3 printf(" EulerSieve: a method to find out all primes below the number that you specify here please: ");
4 std::string strInput;
5 getline(std::cin, strInput);
6 s_last = strtoul(strInput.c_str(), 0, 10);
7 if (s_last <= 2) {
8 printf("\n Wrong input.\n");
9 return 0;
10 }
11 printf("\n Only the sum of all primes needed [y/n](y as default): ");
12 getline(std::cin, strInput);
13 bool bDetail = (strInput == "n");
14 if (bDetail)
15 printf("\n Start to work out all primes below %u...\n", s_last);
16 else
17 printf("\n Start to work out the sum of all primes below %u...\n", s_last);
18 if (!eulerSieve())
19 return 0;
20 if (bDetail)
21 showDetails();
22 return 0;
23 }

eulerSieve函数实现

 1 bool eulerSieve()
2 {
3 DWORD tickBegin = GetTickCount();
4 s_pAll = new u8[s_last];
5 if (!s_pAll) {
6 printf("Lack of memory.\n");
7 return false;
8 }
9
10 ulong sum = 0;
11 memset(s_pAll, 1, s_last);
12 for (ulong num = 2; num < s_last; ++num) {
13 if (s_pAll[num - 1] == 1) {
14 ++sum;
15 s_vecPrime.push_back(num);
16 }
17 for (ulong idx = 0; idx < sum; ++idx) {
18 ulong prime = s_vecPrime[idx];
19 ulong multiple = num * prime;
20 if (multiple >= s_last)
21 break;
22 s_pAll[multiple - 1] = 0;
23 if (num % prime == 0)
24 break;
25 }
26 }
27 printf(" %u primes found in %u milliseconds.\n\n", sum, GetTickCount() - tickBegin);
28 delete []s_pAll;
29 return true;
30 }

showDetails函数实现和Eratosthenes筛法里的实现完全一样。

运行示例

PS H:\Read\num\x64\Release> .\eulerSieve
EulerSieve: a method to find out all primes below the number that you specify here please: 1234567890

Only the sum of all primes needed [y/n](y as default):

Start to work out the sum of all primes below 1234567890...
62106578 primes found in 15734 milliseconds.

PS H:\Read\num\x64\Release> .\eulerSieve
EulerSieve: a method to find out all primes below the number that you specify here please: 123456789

Only the sum of all primes needed [y/n](y as default):

Start to work out the sum of all primes below 123456789...
7027260 primes found in 1391 milliseconds.

PS H:\Read\num\x64\Release> .\eulerSieve
EulerSieve: a method to find out all primes below the number that you specify here please: 12345678

Only the sum of all primes needed [y/n](y as default):

Start to work out the sum of all primes below 12345678...
809227 primes found in 141 milliseconds.

PS H:\Read\num\x64\Release> .\eulerSieve
EulerSieve: a method to find out all primes below the number that you specify here please: 100

Only the sum of all primes needed [y/n](y as default): n

Start to work out all primes below 100...
25 primes found in 0 milliseconds.

2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97
PS H:\Read\num\x64\Release>

对比用C++实现的Eratosthenes筛法程序里的eSieve和用C++实现的增强Eratosthenes筛法程序里的eSievePro,eulerSieve的性能优于eSieve,但不如eSievePro。

其他

https://github.com/readalps/EulerSieve上放了EulerSieve实现的源码文件,以及一个运行结果文件。

用C++实现的Euler筛法程序的更多相关文章

  1. 用C++实现的增强Euler筛法程序

    运行示例 PS H:\Read\num\x64\Release> .\eulerSievePro EulerSievePro: a method to find out all primes b ...

  2. 用C++实现的增强Eratosthenes筛法程序

    运行示例 PS H:\Read\num\x64\Release> .\eSievePro Eratosthenes sieve: a method to find out all primes ...

  3. 用C++实现的Eratosthenes筛法程序

    运行示例 只输出素数总数的运行示例 PS H:\Read\num\x64\Release> .\esieve.exe Eratosthenes sieve: a method to find o ...

  4. [原]素数筛法【Sieve Of Eratosthenes + Sieve Of Euler】

    拖了有段时间,今天来总结下两个常用的素数筛法: 1.sieve of Eratosthenes[埃氏筛法] 这是最简单朴素的素数筛法了,根据wikipedia,时间复杂度为 ,空间复杂度为O(n). ...

  5. USACO1.5Superprime Rid[附带关于素数算法时间测试]

    题目描述 农民约翰的母牛总是产生最好的肋骨.你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们.农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还剩下的肋骨上的数字都组 ...

  6. 素数筛 codevs 1675 大质数 2

    1675 大质数 2  时间限制: 1 s  空间限制: 1000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 小明因为没做作业而被数学 ...

  7. go并发3

    Go语言并发的设计模式和应用场景 以下设计模式和应用场景来自Google IO上的关于Goroutine的PPT:https://talks.golang.org/2012/concurrency.s ...

  8. Go语言并发与并行学习笔记(三)

    转:http://blog.csdn.net/kjfcpua/article/details/18265475 Go语言并发的设计模式和应用场景 以下设计模式和应用场景来自Google IO上的关于G ...

  9. Go语言语法说明

    Go语言语法说明 go语言中的go func(){}() 表示以并发的方式调用匿名函数func 深入讲解Go语言中函数new与make的使用和区别 前言 本文主要给大家介绍了Go语言中函数new与ma ...

随机推荐

  1. vue tab实现右定位

    呈现效果 利用v-if进行判断,登页面完全加载完毕后,显示tab页, 利用name标签,实现选择哪个tab <template> <el-tabs v-if="displa ...

  2. java基于mongodb实现分布式锁

    原理 通过线程安全findAndModify 实现锁 实现 定义锁存储对象: /** * mongodb 分布式锁 */ @Data @NoArgsConstructor @AllArgsConstr ...

  3. jquery点击空白处事件

    $(document).live('click',function(){       $('.emails').hide();   }); 此代码为点击空白处,'emails',标签隐藏.

  4. SpringCloud升级之路2020.0.x版-4.maven依赖回顾以及项目框架结构

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们先来回顾下 m ...

  5. 用KeePass管理密码并用Synology_Drive或者GoodSync实时双向同步电脑桌面和群晖NAS2021年8月5日

    用KeePass管理密码并用Synology_Drive或者GoodSync实时双向同步电脑桌面和群晖NAS2021年8月5日 我通常会把所有办公文档.办公表格和办公图片都实时同步保存到 Synolo ...

  6. 字符串对比 BASIC-15

    字符串对比 代码 import java.util.Scanner; /*给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一: 1:两个字符串长度不等 ...

  7. Linux中的DNS的正解析

    目录 一.DNS概述 1.1.DNS定义 1.2.域名结构 1.3.DNS域名解析的方式 1.4.DNS服务器类型 1.5.BIND服务 BIND服务器端程序 二.构建DNS域名正向解析步骤 一.DN ...

  8. tomcat服务监控分析及自启

    #! /bin/bash # process-monitor.sh serverName="/usr/local/apache-tomcat-7.0.72-8080" #获取进程i ...

  9. tomcat 配置http跳转https

    web.xml增加配置 <security-constraint> <web-resource-collection > <web-resource-name >S ...

  10. SpringBoot-静态资源加载-源码

    目录 静态资源映射规则 什么是webjars 呢? 第二种静态资源映射规则 参考链接 静态资源映射规则 SpringBoot中,SpringMVC的web配置都在 WebMvcAutoConfigur ...