素数总是一个比较常涉及到的内容,掌握求素数的方法是一项基本功。

基本原则就是题目如果只需要判断少量数字是否为素数,直接枚举因子2 。。N^(0.5) ,看看能否整除N。

如果需要判断的次数较多,则先用下面介绍的办法预处理。

一般的线性筛法

首先先介绍一般的线性筛法求素数

void make_prime()  {

memset(prime, 1, sizeof(prime));

prime[0]=false;

prime[1]=false;

int N=31700;

for (int i=2;  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' 就和前面重复了。

需要证明的东西:

  1. 一个数会不会被重复筛除。
  2. 合数肯定会被干掉。

根据上面红字的条件,现在分析一个数会不会被重复筛除。

设这个数为 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 = 200000;

long prime[N] = {0},num_prime = 0;

int isNotPrime[N] = {1, 1};

int main()

{

for(long i = 2 ; i < N ; i ++)

{

if(! isNotPrime[i])

prime[num_prime ++]=i;

//关键处1

for(long j = 0 ; j < num_prime && i * prime[j] <  N ; j ++)

{

isNotPrime[i * prime[j]] = 1;

if( !(i % prime[j] ) )  //关键处2

break;

}

}

return 0;

}

还有一种方法,即第一篇博客说的,实际上是幼拉脱斯展纳筛法,但只是作为学术,不怎么常用

int * eratosthenes(int n){    int a=sqrt(n);    int* array=new int[n+1];    for(int i=0;i<n+1;i++){        array[i]=i;    }    array[1]=0;    for(int i=2;i<a+1;i++){        if(array[i]!=0){            for(int j=i+i;j<n+1;j+=i){                array[j]=0;            }        }    }    return array;}
  1. 打印质数的各种算法 http://coolshell.cn/articles/3738.html  里面有个用C++模板实现的,纯属开阔眼界,不怎么实用。
  2. 检查素数的正则表达式  http://coolshell.cn/articles/2704.html  数字n用  1111。。1 (n个1)表示,纯属坑爹。

一般筛法和快速线性筛法求素数 求素数的一点总结相关推荐

  1. 一般筛法求素数+快速线性筛法求素数

    一般筛法求素数+快速线性筛法求素数 标签: 正则表达式算法优化扩展c 2010-08-22 01:28 28738人阅读 评论(8) 收藏 举报  分类: 算法学习资料(5)  版权声明:本文为博主原 ...

  2. 求素数: 一般线性筛法 + 快速线性筛法

    From: http://blog.csdn.net/dinosoft/article/details/5829550 素数总是一个比较常涉及到的内容,掌握求素数的方法是一项基本功. 基本原则就是题目 ...

  3. 线性筛法求素数c语言,[算法]素数筛法(埃氏筛法线性筛法)

    一.素数筛的定义 给定一个整数n,求出[1,n]之间的所有质数(素数),这样的问题为素数筛(素数的筛选问题). 二.埃氏筛法(Eratosthenes筛法) 埃氏筛法又叫做Eratosthenes筛法 ...

  4. 线性筛法--有测试代码

    //线性筛法--有测试代码 /* 数论 - 欧拉筛法(线性筛)的解释 https://blog.csdn.net/Losk_0/article/details/87884390素数筛法详解(欧拉筛&a ...

  5. 快速求素数表——埃氏筛法与欧拉筛法

    快速求素数表--埃氏筛法与欧拉筛法 快速求素数表埃氏筛法与欧拉筛法 埃氏筛法 埃氏筛法原理 埃氏筛法时间复杂度 埃氏筛法代码求出1000000以内的素数并且输出n个素数 欧拉筛法 欧拉筛法原理 欧拉筛 ...

  6. 线性筛法 与 线性求欧拉函数 的计算模板

    简介 懂得如何快速计算质数是十分重要的 在筛法的基础上,我们可以使用更为高级的线性筛法! 顾名思义,就是时间复杂度是线性的,即 O(N)O(N) ,N 为所求的质数范围 而对编程有所接触的人,应该都知 ...

  7. AcWing 874. 筛法求欧拉函数(线性筛法求欧拉函数模板)

    给定一个正整数 n,求 1∼n 中每个数的欧拉函数之和. 输入格式 共一行,包含一个整数 n. 输出格式 共一行,包含一个整数,表示 1∼n 中每个数的欧拉函数之和. 数据范围 1≤n≤10^6 输入 ...

  8. 线性筛法求质数分解、欧拉函数

    普通筛法的缺点是:对于n,它的质因子有p1,p2,p3,那么n会被划掉3次. 线性筛法的核心思想是:对于n,它只被它的最小质因子p1划掉1次. 线性筛法略加变形即可用来求质数分解和欧拉函数. 求质数分 ...

  9. 素数筛法(传统普通、朴素筛法、埃式筛法、欧拉筛法(线性筛))

    素数筛法(普通.朴素筛法.埃式筛法.欧拉筛法) 1.题目 2.分析 3.代码 传统普通 朴素筛法 朴素筛法(6.14) 埃式筛法 埃式筛法(6.14) 欧拉筛法(线性筛) 欧拉筛法(线性筛 6.14) ...

最新文章

  1. 他们用卷积神经网络,发现了名画中隐藏的秘密
  2. 我这么讲线索二叉树,我三岁大的表弟笑了笑
  3. MyBatis查询结果resultType返回值类型详细介绍
  4. 限制 TEdit 只能接收 数字 输入...
  5. linux之可视化查看磁盘大小并且删除大文件
  6. MySQL多对多创建表语句(防忘记)
  7. spring-mvc教程_使用MVC模式制作游戏-教程和简介
  8. [引]VS2005 之 Visual Basic 程序的结构
  9. java 注解原理_在java中实现组合注解原理分析(注解继承)
  10. java classnotfoundexception e_关于解释class文件时出现java.lang.ClassNotFoundException的问题...
  11. 提高网页效率的14条准则
  12. 世界上最早的手动计算机,世界上第一台电子计算机诞生于多少年,名字叫做什么...
  13. Linux2.6--中断机制中的 ksoftirqd
  14. 中兴echat_在追随用户的路上创新不止 — 中兴高达mini eChat解决方案
  15. Kafka丢数据、重复消费、顺序消费的问题
  16. Tera-Store高速数据采集存储系统
  17. Spring框架学习笔记(三)(AOP,事务管理)
  18. 黑进腾讯内部系统,攻破论坛服务器,揭晓16岁天才黑客背后的真相
  19. COMSOL 报错信息、常见问题和实用解决方法
  20. 在美国创业公司工作经验分享

热门文章

  1. css 如何让背景图片拉伸填充避免重复显示
  2. Linux虚机安装配置Tomcat
  3. 单片机串行通信全解析
  4. jquery获得下拉框的值
  5. Proximal Algorithms--Accelerated proximal gradient method
  6. node模块函数图解
  7. android手机最低内存,原神手机端需要哪些配置 手机端最低配置要求介绍
  8. unity烘培单个物体_Unity可编程渲染管线(SRP)教程:二、自定义着色器
  9. java 分布式编译_linux分布式编译distcc和ccache的部署
  10. python将图像转换为8位单通道_使用Python将图片转换为单通道黑白图片