ACM数论——素数 


素数定义

质数(prime number)又称素数,有无限个。质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数,这样的数称为质数。例 子:2、3、5、7、11、13、17、19。(那时候还有一种说法叫做“质数”,但是就语言上来说,我觉得“素数”这种叫法和“合数”比较搭配,类比于“化学元素”和“化合物”来看,叫“素数”非常贴切)

素数一些性质:

  1. 质数p的约数只有两个:1和p;
  2. 任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,这种分解是唯一的;
  3. 一个偶数可以写成两个合数之和,其中每一个合数都最多只有9个质因数;
  4. 一个偶数必定可以写成一个质数加上一个合成数,其中合数的因子个数有上界;

素数应用:

  1. 数学上来看,质数有很多尚未证明的特性;应用上的话,公钥密码是一比较好的例子了。
  2. 素数对于数论就好像元素对于化学。(摘自知乎)

判断素数:

 //判断是否是一个素数
int IsPrime(int x)
{
if(x<=) //0,1,负数都是非素数
return ;
int ans=(int)sqrt(x)+; /*计算枚举上界,为防止ans值带来的精度损失,所以采用根号值取整后再加1,即宁愿多枚举一个,也不愿少枚举一个数 */
for(int i=; i<ans; i++)
{
if(x%i==)
{
return ;
}
}
return ;
}

 素数筛法:

  1.开一个大的bool型数组prime[],大小就是n+1就可以了.先把所有的下标为奇数的标为true,下标为偶数的标为false.

  2.代码如下:

for( i=3; i<=sqrt(n); i+=2 )
{
if(prime[i])
 for( j=i+i; j<=n; j+=i )
prime[j]=false;
}

3.最后输出bool数组中的值为true的单元的下标,就是所求的n以内的素数了。
      原理很简单,就是当i是质(素)数的时候,i的所有的倍数必然是合数。如果i已经被判断不是质数了,那么再找到i后面的质数来把这个质数的倍数筛掉。 
    一个简单的筛素数的过程:n=30。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

第 1 步过后4 ... 28 30这15个单元被标成false,其余为true。
    第 2 步开始:
     i=3; 由于prime[3]=true, 把prime[6], [9], [12], [15], [18], [21], [24], [27], [30]标为false.
     i=4; 由于prime[4]=false,不在继续筛法步骤。
     i=5; 由于prime[5]=true, 把prime[10],[15],[20],[25],[30]标为false.
     i=6>sqrt(30)算法结束。
    第 3 步把prime[]值为true的下标输出来:
     for(i=2; i<=30; i++)
       if(prime[i]) printf("%d ",i);
    结果是 2 3 5 7 11 13 17 19 23 29

  下图为n=120的素数筛:

// 1:这是最原始的素数筛法
#define Max 1000000
bool prime[Max];
void IsPrime(){
prime[]=prime[]=;prime[]=;
for(int i=;i<max;i++)
prime[i]=i%==?:;
int t=(int)sqrt(Max*1.0);
for(int i=;i<=t;i++)
if(prime[i])
for(int j=i;j<Max;j+=i)
prime[j]=;
}
//2:优化后的筛法,手动地模拟原始筛法就可以发现,某个数字可能被不止一次地删去
// 优化后的筛法就可以避免这种不必要的删去操作
#define Max 1000000
bool prime[Max];
void IsPrime(){
prime[]=prime[]=;prime[]=;
for(int i=;i<max;i++)
prime[i]=i%==?:;
int t=(int)sqrt(Max*1.0);
for(int i=;i<=t;i++)
if(prime[i])
for(int j=i*i;j<Max;j+=*i)//优化
prime[j]=;
}

 快速线性筛法 :

  上面的方法比较好理解,初始时,假设全部都是素数,当找到一个素数时,显然这个素数乘上另外一个数之后都是合数

  把这些合数都筛掉,即算法名字的由来。但仔细分析能发现,这种方法会造成重复筛除合数,影响效率。

  比如10,在i=2的时候,k=2*15筛了一次;在i=5,k=5*6 的时候又筛了一次。所以,也就有了快速线性筛法。

  利用了每个合数必有一个最小素因子。每个合数仅被它的最小素因子筛去正好一次。所以为线性时间。

void get_prime()
{
int cnt = ;
for (int i = ; i < N; i++)
{
if (!tag[i]) p[cnt++] = i;
for (int j = ; j < cnt && p[j] * i < N; j++)
{
tag[i*p[j]] = ;
if (i % p[j] == )
break;
}
}
}

函数模板

 我推荐这个算法! 易于理解,只算奇数部分,时空效率都还不错!
half=SIZE/;
int sn = (int) sqrt(SIZE);
for (i = ; i < half; i++)
p[i] = true;// 初始化全部奇数为素数。p[0]对应3,即p[i]对应2*i+3
for (i = ; i < sn; i++) {
if(p[i])//如果 i+i+3 是素数
{
for(k=i+i+, j=k*i+k+i; j < half; j+=k)
// 筛法起点是 p[i]所对应素数的平方 k^2
// k^2在 p 中的位置是 k*i+k+i
// 下标 i k*i+k+i
//对应数值 k=i+i+3 k^2
p[j]=false;
}
}
//素数都存放在 p 数组中,p[i]=true代表 i+i+2 是素数。
//举例,3是素数,按3*3,3*5,3*7...的次序筛选,因为只保存奇数,所以不用删3*4,3*6....

推荐


ACM数论-素数的更多相关文章

  1. ACM数论-欧几里得与拓展欧几里得

    ACM数论——欧几里得与拓展欧几里得 欧几里得算法: 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd ...

  2. ACM数论总结

    ACM数论总结 http://blog.csdn.net/xieshimao/article/details/6425099 断断续续的学习数论已经有一段时间了,学得也很杂,现在进行一些简单的回顾和总 ...

  3. acm数论之旅--欧拉函数的证明

    随笔 - 20  文章 - 0  评论 - 73 ACM数论之旅7---欧拉函数的证明及代码实现(我会证明都是骗人的╮( ̄▽ ̄)╭) https://blog.csdn.net/chen_ze_hua ...

  4. acm数论之旅--数论四大定理

    ACM数论之旅5---数论四大定理(你怕不怕(☆゚∀゚)老实告诉我)   (本篇无证明,想要证明的去找度娘)o(*≧▽≦)ツ ----------数论四大定理--------- 数论四大定理: 1.威 ...

  5. 卡特兰数 Catalan数 ( ACM 数论 组合 )

    卡特兰数 Catalan数 ( ACM 数论 组合 ) Posted on 2010-08-07 21:51 MiYu 阅读(13170) 评论(1)  编辑 收藏 引用 所属分类: ACM ( 数论 ...

  6. ACM数论-快速幂

    ACM数论——快速幂 快速幂定义: 顾名思义,快速幂就是快速算底数的n次幂.其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高. 原理: 以下以求a的b次方来介绍: 把b转换成 ...

  7. acm数论之旅--中国剩余定理

    ACM数论之旅9---中国剩余定理(CRT)(壮哉我大中华╰(*°▽°*)╯)   中国剩余定理,又名孙子定理o(*≧▽≦)ツ 能求解什么问题呢? 问题: 一堆物品 3个3个分剩2个 5个5个分剩3个 ...

  8. acm数论之旅--组合数(转载)

    随笔 - 20  文章 - 0  评论 - 73 ACM数论之旅8---组合数(组合大法好(,,• ₃ •,,) )  补充:全错排公式:https://blog.csdn.net/Carey_Lu/ ...

  9. acm数论之旅(转载) -- 逆元

    ACM数论之旅6---数论倒数,又称逆元(我整个人都倒了( ̄﹏ ̄))   数论倒数,又称逆元(因为我说习惯逆元了,下面我都说逆元) 数论中的倒数是有特别的意义滴 你以为a的倒数在数论中还是1/a吗 ( ...

随机推荐

  1. 条件独立(conditional independence) 结合贝叶斯网络(Bayesian network) 概率有向图 (PRML8.2总结)

    转:http://www.cnblogs.com/Dzhouqi/p/3204481.html本文会利用到上篇,博客的分解定理,需要的可以查找上篇博客 D-separation对任何用有向图表示的概率 ...

  2. SAP CRM系统订单模型的设计与实现

    SAP成都研究院的一个部门领导让我给他的团队做一个SAP CRM One Order框架的培训,这是我准备的培训内容. 在Jerry之前的文章 基于SAP Kyma的订单编排增强介绍,我表达了自己对S ...

  3. monodevelop 基础用法

    1.mono快捷键      CTRL+K  删除光标所在行的该行后面的代码 CTRL + ALT +C  注释/不注释该行 CTRL+ DOWN  像鼠标滚轮一样向下拖 CTRL + UP 像鼠标滚 ...

  4. Java---页面之间传值跳转

    从首页A进入页面B,然后从B页面登录,成功后跳转到A页面,并打印一句话“登录成功”,传值需要用的后台的. 在B页面写: <%     session.setAttribute("key ...

  5. R在Centos下安装

    R语言是主要用于统计分析.绘图的语言和操作环境. 官方网站: http://www.r-project.org/ Windows下面有直接的安装包,直接下载安装很方便,但是对于刚出的CentOS6.0 ...

  6. 使用 PHP Curl 做数据中转

    流程 收集头部信息 收集请求数据 转换头部信息为 CURL 头部请求格式 使用 Curl 进行转发 收集 HTTP 头信息 function getAllHeaders() { $headers = ...

  7. MaBatis(5)输入/输出映射

    本次全部学习内容:MyBatisLearning   输入映射: 通过parameType指定输入参数的类型,类型可以是简单类型,hashmap,pojo等     传递pojo的包装对象 需求: 即 ...

  8. ElasticSearch5.0+版本分词热更新实践记录

    前言 刚开始接触ElasticSearch的时候,版本才是2.3.4,短短的时间,现在都更新到5.0+版本了.分词和head插件好像用法也不一样了,本博客记录如何配置Elasticsearch的Hea ...

  9. python-递归的实现

    一.概念 递归算法是一种直接或者间接地调用自身算法的过程,在计算机编写程序中,递归算法对解决一大类问题是十分有效的. 特点: ①递归就是在过程或者函数里调用自身. ②在使用递归策略时,必须有一个明确的 ...

  10. 关键字: simpledateformat24小时 格式串

    SimpleDateFormat 是 Java 中一个非常常用的类,该类用来对日期字符串进行解析和格式化输出   Era 标志符 Text AD y 年 Year 1996; 96 M 年中的月份 M ...