判断素数或者求出素数的基本算法 《挑战程序设计竞赛》
2018-2-28
首先我们得明确一个概念,那就是什么是素数,据我的了解,素数就是除了1和它本身之外,不存在其他的因数的数。
1.素性测试
判断给定的数n是否是素数
这应该是最简单的了,直接从2至n,如果存在n对其求余为0的话,那就不是素数了,这里可以降低我们的复杂度,想一下,如果一个数i是n的因子,那么n/i也必定是n的因子,不妨设i<=n/i,那么i最大的值就是sqrt(n)了,那么我们的循环也只要从2到sqrt(n)就可以了,因为这个算法比较普遍,我就不附上代码了。
2.埃氏筛法
求出给定整数n以内有多少个素数
如果用上面的算法,那么n以内的所有数都要进行一遍素数测试,那么时间复杂度为O(n^2),可想而知这样的效果不是特别好。
对于2而言,2的倍数4,6,8…那就都不是素数了,
对于3而言,3的倍数6,9,12…那也都不是素数了,
如果当前的数m是素数,那么m的倍数就都不是倍数了,有的人可能会问,为什么m就是素数呢,我们想一下如果m不是素数的话,那么它一定可以表示为p*q的积,不妨我们设这里的p为素数(如果p不是素数还可以再拆,直至变为素数),那么我们在遇到p这个素数的时候,就已经把m,这个素数p的倍数划掉了,所以这样反复操作就能得到我们要的素数了。
#include<iostream>
#include<cstring>
using namespace std;const int N = 100;
bool is_prime[N+1];
int prime[N+1];int main(){memset(is_prime,true,sizeof(is_prime));is_prime[0]=false;is_prime[1]=false;int cnt=0;for (int i=2;i<=N;i++){if (is_prime[i]){prime[cnt++]=i;for (int j=i*i;j<=N;j+=i){is_prime[j]=false;}}}for (int i=0;i<cnt;i++){cout<<prime[i]<<" ";}cout<<"cnt="<<cnt<<endl;// for (int i=2;i*i<=N;i++){// if (is_prime[i]){// for (int j=i*i;j<=N;j+=i){// is_prime[j]=false;// }// }// }// int cnt=0;// for (int i=0;i<=N;i++){// if (is_prime[i]) prime[cnt++]=i;// }// for (int i=0;i<cnt;i++){// cout<<prime[i]<<" ";// }// cout<<"cnt="<<cnt<<endl;return 0;
}
这里的j有的人可能会想从2*i开始,其实从2*i到(i-1)*i都已经在’i’为2到i-1的时候被计算过了,所以我们这里会选择从i*i开始。
3.区间筛法
给定区间[a,b),求出他们两个数之间素数的个数
对于[a,b)内的合数而言,它们的因子应该在2到sqrt(b)之间,那么我们只要把2到sqrt(n)的倍数在给定区间[a,b)的数筛掉就可以了,为了节省我们的存储空间,我们可以将[a,b),左移到[0,b-a)就可以了。
#include<iostream>
#include<cstring>
using namespace std;typedef long long int ll;
const int N = 1000000;
bool is_prime_small[N+1],is_prime[N+1];
ll a,b;int main(){while (cin>>a>>b){memset(is_prime,true,sizeof(is_prime));memset(is_prime_small,true,sizeof(is_prime_small));is_prime_small[0]=false;is_prime_small[1]=false;if (a==0){is_prime[0]=false;is_prime[1]=false;}else if (a==1){is_prime[0]=false;}for (ll i=2;i*i<b;i++){if (is_prime_small[i]){for (ll j=i*i;j<b;j+=i){if (j>=a) is_prime[j-a]=false;//在对应区间的数就不是素数了}for (ll j=i*i;j*j<b;j+=i) is_prime_small[j]=false;//将[2,sqrt(b))内的素数筛出来}}int cnt=0;for (ll i=0;i<b-a;i++){if (is_prime[i]){cnt++;cout<<i+a<<" ";}}cout<<"cnt="<<cnt<<endl;}return 0;
}
除此之外还有其他素数有关的算法,不过程序设计竞赛主要就是涉及这三种。
最后给一个第八届蓝桥杯b组的试题:
2,3,5,7,11,13,....是素数序列。
类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。
上边的数列公差为30,长度为6。2004年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。
这是数论领域一项惊人的成果!有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:长度为10的等差素数列,其公差最小值是多少?注意:需要提交的是一个整数,不要填写任何多余的内容和说明文字。
如果我没记错的话,当时比赛的时候好像是错的。。。
首先我们需要把1000000以内的所有素数筛选出来,这样可以简化我们后边的计算,然后我们对d以及首项a1进行遍历,然后依次判断即可。
刚开始的时候我还在纠结一个问题,也就是说如果当前的cnt正好等于M=10,那么是否存在a1-d正好也是素数,那么这里是不是就多了一个了,变成M+1个了,后来我发现,不存在的,在我这里,以a1-d为首项的等差数列的d’一定小于d。
#include<iostream>
#include<cstring>
using namespace std;const int N = 1000000, M = 10;
bool is_prime[N+1];int main(){memset(is_prime,true,sizeof(is_prime));for (int i=2;i*i<=N;i++){if (is_prime[i]){for (int j=i*i;j<=N;j+=i){is_prime[j]=false;}}}int i,cnt;bool flag=false;for (i=2;;i++){for (int j=2;j<=N;j++){if (!is_prime[j]) continue;cnt=1;for (int k=j+i;k<=N;k+=i){if (!is_prime[k]||cnt>M) break;if (is_prime[k]){cnt++;}}if (cnt==M){flag=true;break;}}if (flag) break;}cout<<i<<endl;return 0;
}
虽然运行的时候停顿了一下,但是最后还是得到了结果210。
判断素数或者求出素数的基本算法 《挑战程序设计竞赛》相关推荐
- c语言给定整数求紧随素数,C语言:找出一个大于给定整数m且紧随m的素数,-求出能整除x且不是偶数的数的个数,...
//函数fun功能:找出一个大于给定整数m且紧随m的素数,并作为函数值返回. #include #include #include int fun( int m) { int i,k; for (i= ...
- java写100以内的素数_求出100以内的素数(java实现)
j package test1; //2018/11/30 //求100以内的所有素数 public class Main10 { public static void main(String[] a ...
- 等价关系运算c语言大作业,如何用c语言编写:n等价关系判断,并求出等价类及其元素...
满意答案 guigui5418 2015.05.18 采纳率:48% 等级:8 已帮助:1460人 12345678910111213141516171819202122232425262728 ...
- MySQL素数怎么,求质数(素数)的方法
质数是数学重要的一环,所谓质数,就是除了1和它本身外不存在任何因子的数.以下整理了一下c语言中质数的求法. 问题:输入一个正整数n(n>=2),求不大于n的全部质数 方法一:循环法 思路:判断一 ...
- 挑战程序设计竞赛部分题目选择排序、二分查找找出下标、深度优先算法、求三角形max周长、蚂蚁算法、操作excel
首先提供帮助类 可能这个类还需要更新 .求最大值.求最小值.选择排序.二分查找找出下标.二分查找排好序列里面是否有那个值 public class Util {//求最大值public static ...
- php算法求出兔子数列,PHP算法:斐波那契数列的N种算法
前言 前段时间,遇到优化计算斐波那契数列的常规递归方法,但是一时间并没有及时想到很好的方法,所以后面查找了相关资料,总结了多种计算解法,所以分享出来,和大家一起交流学习. 斐波那契数是什么 斐波那契数 ...
- 求余小技巧 码农场 » POJ 3641 Pseudoprime numbers 题解 《挑战程序设计竞赛》
// return (a * b) % m LL mod_mult(LL a, LL b, LL m) {LL res = 0;LL exp = a % m;while (b){if (b & ...
- c语言练习7——求出小于或等于lim的所有素数应放在aa数组中
功能:求出小于或等于lim的所有素数应放在aa数组中,并返回所求出素数的个数 思路:1)使用for循环查找所有小于lim的数: 2)使用内循环判断是否为素数: #include<conio.h& ...
- 俄罗斯套娃素数c语言解法,求俄罗斯套娃素数(BFS)
求俄罗斯套娃素数(BFS) 求俄罗斯套娃素数(BFS) [var1] #pragma GCC optimize(2) #include #include #include #include #incl ...
最新文章
- 数字图像处理:(1)图像梯度以及算子应用
- json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) 问题解决
- Linux 打开/关闭CPU命令
- stm32f103 spi crc
- node-glob 正则表达式
- html文档定义层标记是,jsp练习题目201312
- Hadoop配置项整理(hdfs-site.xml)
- 资源放送丨《高并发Oracle OLTP系统的故障案例分享》PPT视频
- 深度学习TF—3.神经网络全连接层
- 基于百度翻译api的命令行翻译助手
- div+css三栏式布局
- Word插入Excel的时候报错:用于创建此对象的程序是Excel
- 大数据数据库:MPP vs MapReduce
- 帝国cms弱口令登录(帝国cms后台密码忘记怎么办?)
- eap wifi 证书_用openssl为EAP-TLS生成证书(CA证书,服务器证书,用户证书)
- OverTheWire-Bandit
- 第二章:关系数据库 - 04735数据库系统原理 - 自考知识点
- 在各种裁员的“寒冬”,还应该对年终奖有多少期待?!
- CainAbel工具的下载和使用
- 心率变异性 matlab,心率变异性好的功率谱分析方面的问题