<转载>一般筛法和快速线性筛法求素数
素数总是一个比较常涉及到的内容,掌握求素数的方法是一项基本功。
基本原则就是题目如果只需要判断少量数字是否为素数,直接枚举因子2 。。N^(0.5) ,看看能否整除N。
如果需要判断的次数较多,则先用下面介绍的办法预处理。
一般的线性筛法
首先先介绍一般的线性筛法求素数
void make_prime() {
memset(prime, , sizeof(prime));
prime[]=false;
prime[]=false;
int N=;
for (int i=; i<N; i++) if (prime[i]) { primes[++cnt ]=i; for (int k=i*i; k<N; k+=i)
prime[k]=false;
}
return;
}
这种方法比较好理解,初始时,假设全部都是素数,当找到一个素数时,显然这个素数乘上另外一个数之后都是合数(注意上面的 i*i , 比 i*2 要快点 ),把这些合数都筛掉,即算法名字的由来。
但仔细分析能发现,这种方法会造成重复筛除合数,影响效率。比如10,在i=2的时候,k=2*15筛了一次;在i=5,k=5*6 的时候又筛了一次。所以,也就有了快速线性筛法。
快速线性筛法
快速线性筛法没有冗余,不会重复筛除一个数,所以“几乎”是线性的,虽然从代码上分析,时间复杂度并不是O(n)。先上代码
首先,先明确一个条件,任何合数都能表示成一系列素数的积。
不管 i 是否是素数,都会执行到“关键处1”,
①如果 i 都是是素数的话,那简单,一个大的素数 i 乘以不大于 i 的素数,这样筛除的数跟之前的是不会重复的。筛出的数都是 N=p1*p2的形式, p1,p2之间不相等
②如果 i 是合数,此时 i 可以表示成递增素数相乘 i=p1*p2*...*pn, pi都是素数(2<=i<=n), pi<=pj ( i<=j )
p1是最小的系数。
根据“关键处2”的定义,当p1==prime[j] 的时候,筛除就终止了,也就是说,只能筛出不大于p1的质数*i。
我们可以直观地举个例子。i=2*3*5
此时能筛除 2*i ,不能筛除 3*i
如果能筛除3*i 的话,当 i' 等于 i'=3*3*5 时,筛除2*i' 就和前面重复了。
需要证明的东西:
- 一个数会不会被重复筛除。
- 合数肯定会被干掉。
根据上面红字的条件,现在分析一个数会不会被重复筛除。
设这个数为 x=p1*p2*...*pn, pi都是素数(1<=i<=n) , pi<=pj ( i<=j )
当 i = 2 时,就是上面①的情况,
当 i >2 时, 就是上面②的情况, 对于 i ,第一个能满足筛除 x 的数 y 必然为 y=p2*p3...*pn(p2可以与p1相等或不等),而且满足条件的 y 有且只有一个。所以不会重复删除。
证明合数肯定会被干掉? 用归纳法吧。
类比一个模型,比如说我们要找出 n 中2个不同的数的所有组合 { i , j } ,1<=i<=n, 1<=j<=n,
我们会这么写
for (i=1; i<n; ++i )
for (j=i+1; j<=n; ++j)
{
.....
}
我们取 j=i+1 便能保证组合不会重复。快速筛法大概也是这个道理,不过这里比较难理解,没那么直观。
第一种的优化,先判断奇偶。
#include<iostream>
using namespace std;
const long N = ;
long prime[N] = {},num_prime = ;
int isNotPrime[N] = {, };
int main()
{
for(long i = ; i < N ; i ++) {
if(! isNotPrime[i])
prime[num_prime ++]=i; //关键处1
for(long j = ; j < num_prime && i * prime[j] < N ; j ++)
{
isNotPrime[i * prime[j]] = ;
if( !(i % prime[j] ) ) //关键处2
break;
}
}
return ;
}
还有一种方法,即第一篇博客说的,实际上是幼拉脱斯展纳筛法,但只是作为学术,不怎么常用
int * eratosthenes(int n) {
int a=sqrt(n);
int* array=new int[n+];
for(int i=; i<n+; i++) {
array[i]=i;
}
array[]=;
for(int i=; i<a+; i++) {
if(array[i]!=) {
for(int j=i+i; j<n+; j+=i) {
array[j]=;
}
}
}
return array;
}
- 打印质数的各种算法 http://coolshell.cn/articles/3738.html 里面有个用C++模板实现的,纯属开阔眼界,不怎么实用。
2.检查素数的正则表达式 http://coolshell.cn/articles/2704.html 数字n用 1111。。1 (n个1)表示,纯属坑爹。
转载原文:http://blog.csdn.net/bobodem/article/details/49386119
<转载>一般筛法和快速线性筛法求素数的更多相关文章
- Algorithm --> 筛法求素数
一般的线性筛法 genPrime和genPrime2是筛法求素数的两种实现,一个思路,表示方法不同而已. #include<iostream> #include<math.h> ...
- [算法]素数筛法(埃氏筛法&线性筛法)
目录 一.素数筛的定义 二.埃氏筛法(Eratosthenes筛法) 三.线性筛法 四.一个性质 一.素数筛的定义 给定一个整数n,求出[1,n]之间的所有质数(素数),这样的问题为素数筛(素数的筛选 ...
- UVA 10006 - Carmichael Numbers 数论(快速幂取模 + 筛法求素数)
Carmichael Numbers An important topic nowadays in computer science is cryptography. Some people e ...
- noip知识点总结之--线性筛法及其拓展
一.线性筛法 众所周知...线性筛就是在O(n)的时间里找出所有素数的方法 code: void get_prime(int N){ int i, j, k; memset(Flag, ); ; i ...
- 初等数论-Base-1(筛法求素数,欧拉函数,欧几里得算法)
前言 初等数论在OI中应用的基础部分,同机房的AuSquare和zhou2003君早就写完了,一直划水偷懒的Hk-pls表示很方,这才开始了这篇博客. \(P.S.\)可能会分部分发表. Base-1 ...
- 素数筛 : Eratosthenes 筛法, 线性筛法
这是两种简单的素数筛法, 好不容易理解了以后写篇博客加深下记忆 首先, 这两种算法用于解决的问题是 : 求小于n的所有素数 ( 个数 ) 比如 这道题 在不了解这两个素数筛算法的同学, 可能会这么写一 ...
- 蓝桥杯 算法训练 Torry的困惑(基本型)(水题,筛法求素数)
算法训练 Torry的困惑(基本型) 时间限制:1.0s 内存限制:512.0MB 问题描述 Torry从小喜爱数学.一天,老师告诉他,像2.3.5.7……这样的数叫做质数.Torry突 ...
- hdu 4548 筛法求素数 打表
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4548 Problem Description 小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题 ...
- 筛法求素数Java
输出:一个集合S,表示1~n以内所有的素数 import java.util.Scanner; public class 筛法求素数 { public static void main(String[ ...
随机推荐
- Javascript专题(三)b.各种轮播和细节分析--上下滚动轮播
这一次,我们用原生JS实现上下滚动方式的轮播.顺带学习一下用JS来创建HTML元素. 上一次写的轮播是淡入淡出效果的,相对来说其实是比较简单的. github源码: 上下轮播源码-github A. ...
- Eclipse中mybatis的xml文件没有提示,出现the file cannot be validated as the XML definition.....
1.下载dtd文件 2.在eclipse中配置本地dtd文件: Window->Preferences->XML->XML Catalog->User Specified En ...
- C++之Vect
在C++中数组和向量都是多同类元素的集合,他们也有很明显的区别 1 数组属于静态分配,编译之前必须知道数组的大小,一旦确定就不能更改:2个数组之间不能直接赋值实现拷贝,而必须显式用for或者拷贝函数拷 ...
- (一)Redis简介和安装
1 Redis介绍 1.1 什么是NoSql 为了解决高并发.高可扩展.高可用.大数据存储问题而产生的数据库解决方案,就是NoSql数据库. NoSQL,泛指非关系型的数据库,N ...
- Windows下使用nvm管理多个Node.js 版本
下载 https://github.com/coreybutler/nvm-windows/releases 安装 配置 使用 # nvm install 版本号 # nvm list ...
- over partition by与group by
over partition by与group by 的区别 http://www.cnblogs.com/scottpei/archive/2012/02/16/2353718.html 今天看到一 ...
- ios MBProgressHUD 使用,及二次封装
MBProgressHUD是一个显示HUD窗口的第三方类库,用于在执行一些后台任务时,在程序中显示一个表示进度的loading视图和两个可选的文本提示的HUD窗口.MBProgressHUD 二次封装 ...
- 什么是SpringBoot
随着动态语言的流行(Ruby,Groovy,Scala,Node.js),Java的开发显得格外的笨重;繁多的配置,低下的开发效率,复杂的部署流程以及第三方技术集成难度大. 在上述环境 下,Sprin ...
- spring的工厂方法
http://blog.csdn.net/nvd11/article/details/51542360
- MATLAB之折线图、柱状图、饼图以及常用绘图技巧
MATLAB之折线图.柱状图.饼图以及常用绘图技巧 一.折线图 参考代码: %图1:各模式直接成本预测 %table0-table1为1*9的数组,记录关键数据 table0 = data_modol ...