用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 ...
随机推荐
- vue tab实现右定位
呈现效果 利用v-if进行判断,登页面完全加载完毕后,显示tab页, 利用name标签,实现选择哪个tab <template> <el-tabs v-if="displa ...
- java基于mongodb实现分布式锁
原理 通过线程安全findAndModify 实现锁 实现 定义锁存储对象: /** * mongodb 分布式锁 */ @Data @NoArgsConstructor @AllArgsConstr ...
- jquery点击空白处事件
$(document).live('click',function(){ $('.emails').hide(); }); 此代码为点击空白处,'emails',标签隐藏.
- SpringCloud升级之路2020.0.x版-4.maven依赖回顾以及项目框架结构
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们先来回顾下 m ...
- 用KeePass管理密码并用Synology_Drive或者GoodSync实时双向同步电脑桌面和群晖NAS2021年8月5日
用KeePass管理密码并用Synology_Drive或者GoodSync实时双向同步电脑桌面和群晖NAS2021年8月5日 我通常会把所有办公文档.办公表格和办公图片都实时同步保存到 Synolo ...
- 字符串对比 BASIC-15
字符串对比 代码 import java.util.Scanner; /*给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一: 1:两个字符串长度不等 ...
- Linux中的DNS的正解析
目录 一.DNS概述 1.1.DNS定义 1.2.域名结构 1.3.DNS域名解析的方式 1.4.DNS服务器类型 1.5.BIND服务 BIND服务器端程序 二.构建DNS域名正向解析步骤 一.DN ...
- tomcat服务监控分析及自启
#! /bin/bash # process-monitor.sh serverName="/usr/local/apache-tomcat-7.0.72-8080" #获取进程i ...
- tomcat 配置http跳转https
web.xml增加配置 <security-constraint> <web-resource-collection > <web-resource-name >S ...
- SpringBoot-静态资源加载-源码
目录 静态资源映射规则 什么是webjars 呢? 第二种静态资源映射规则 参考链接 静态资源映射规则 SpringBoot中,SpringMVC的web配置都在 WebMvcAutoConfigur ...