用C++实现的Euler筛法程序
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筛法程序的更多相关文章
- 用C++实现的增强Euler筛法程序
运行示例 PS H:\Read\num\x64\Release> .\eulerSievePro EulerSievePro: a method to find out all primes b ...
- 用C++实现的增强Eratosthenes筛法程序
运行示例 PS H:\Read\num\x64\Release> .\eSievePro Eratosthenes sieve: a method to find out all primes ...
- 用C++实现的Eratosthenes筛法程序
运行示例 只输出素数总数的运行示例 PS H:\Read\num\x64\Release> .\esieve.exe Eratosthenes sieve: a method to find o ...
- [原]素数筛法【Sieve Of Eratosthenes + Sieve Of Euler】
拖了有段时间,今天来总结下两个常用的素数筛法: 1.sieve of Eratosthenes[埃氏筛法] 这是最简单朴素的素数筛法了,根据wikipedia,时间复杂度为 ,空间复杂度为O(n). ...
- USACO1.5Superprime Rid[附带关于素数算法时间测试]
题目描述 农民约翰的母牛总是产生最好的肋骨.你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们.农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还剩下的肋骨上的数字都组 ...
- 素数筛 codevs 1675 大质数 2
1675 大质数 2 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 小明因为没做作业而被数学 ...
- go并发3
Go语言并发的设计模式和应用场景 以下设计模式和应用场景来自Google IO上的关于Goroutine的PPT:https://talks.golang.org/2012/concurrency.s ...
- Go语言并发与并行学习笔记(三)
转:http://blog.csdn.net/kjfcpua/article/details/18265475 Go语言并发的设计模式和应用场景 以下设计模式和应用场景来自Google IO上的关于G ...
- Go语言语法说明
Go语言语法说明 go语言中的go func(){}() 表示以并发的方式调用匿名函数func 深入讲解Go语言中函数new与make的使用和区别 前言 本文主要给大家介绍了Go语言中函数new与ma ...
随机推荐
- POJ3048
素数筛,数据范围不大,直接暴力筛. 坑:有个数据是 1 1,答案是1.差点没把我卡去世. 我的三观哪去了. #include<iostream> #include<cstdio> ...
- 配置软ISCSI存储
说明:这里是Linux服务综合搭建文章的一部分,本文可以作为单独使用RedHat Enterprise Linux 7搭建软ISCSI的参考. 注意:这里所有的标题都是根据主要的文章(Linux基础服 ...
- Python基础之subprocess
前言 subprocess这个函数很好用,类似于控制台执行,功能很多,今天先介绍subprocess调用exe,并行调用两个或两个以上的exe. Subprocess调用exe 调用exe有几种方式, ...
- python中的生成器,迭代器及列表生成式
列表生成器: 即List Comprehensions. 在python中,可通过内置的强大有简单的生成式来创建列表.例如创建一个1到10的列表list [1, 2, 3, 4, 5, 6, 7, ...
- jvm源码解读--15 oop对象详解
(gdb) p obj $15 = (oopDesc *) 0xf3885d08 (gdb) p * obj $16 = { _mark = 0x70dea4e01, _metadata = { _k ...
- 看视频学Bootstrap—在微软虚拟学院学习Bootstrap
Bootstrap 是目前最流行的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB项目. 如果您希望在几个小时内对Bootstrap有一个直观的了解,观看微软虚拟学院(M ...
- 解决iOS上网页滑动不流畅问题
body { overflow:auto; /* 用于 android4+,或其他设备 */ -webkit-overflow-scrolling:touch; /* 用于 ios5+ */ }说明: ...
- 字符串匹配算法(三)-KMP算法
今天我们来聊一下字符串匹配算法里最著名的算法-KMP算法,KMP算法的全称是 Knuth Morris Pratt 算法,是根据三位作者(D.E.Knuth,J.H.Morris 和 V.R.Prat ...
- ECShop 2.x/3.x SQL注入/任意代码执行漏洞
poc地址:https://github.com/vulhub/vulhub/blob/master/ecshop/xianzhi-2017-02-82239600/README.zh-cn.md 生 ...
- Vue 动态绑定CSS样式
今天在做项目上遇见了一个需求,通过不能的进度类型展示不同的进度形态,进度形态通过背景色和背景色上的文字显示. 效果图: 由于Element UI版本我用的是2.5.4 使用进度条的话 就没有2.9. ...