ACM-判素数
来源:互联网 发布:计算机最小的数据单位 编辑:程序博客网 时间:2024/04/29 01:39
这篇文章我们将讨论如何求素数,所谓素数即只能被1和本身整除的数,那么毫无疑问,对于一个数n是不是素数,我们可以直接进行判断,即从2~n-1一一进行枚举,如果n都不能被整除,那么说明n就是素数。如果直接暴力判断,需要注意两点:
1、n不能太大
2、只需判断n的根号次
下面是判定素数的源代码:
#include <cmath>int IsPrime(int n){ for(int i=2; i<=sqrt(1.0*n); ++i) if(n%i == 0) return 0; return 1;}
很明显,这样直接枚举判断的时间复杂度很高,下面就讲一种新的方法:筛法,如果用筛法构造素数,可以在很短的时间内算出10^6以内的所有素数,其复杂度为nlog(n)。筛法的原理简单来说就是删除倍数,即对于不超过n的每一个非负整数p,删除2p,3p,4p.,.....,这样处理完每一个p之后,剩下的没有被删除的就是素数,其实这也是素数定义的体现,即能被除了1和自身外的任何数整除的数都不是素数。下面是筛法的源代码:
#include <cmath>#include <cstring>const int MAXN = 1e6;int vis[MAXN+1];int prime[MAXN+1];void IsPrime(int n){ int i, j; int m = sqrt(n+0.5); memset(vis, 0, sizeof(vis)); memset(prime, 0, sizeof(prime)); for(i=2; i<=m; ++i) if(!vis[i]) {prime[i] = 1; // 如果i为素数for(j=i*i; j<=n; j+=i) vis[j] = 1; } for(; i<=n; ++i) if(!vis[i]) prime[i] = 1;}
一般来说上面的算法已经足够快了,但不是最快,因为在存在重复筛数,比如对于2和4来说,都将8、12、16、......、筛除了。要保证不会重复筛除每一个数,即让算法保持线性,可以从奇偶性方面入手,下面是参考代码:
#include <cmath>#include <cstring>const int MAXN = 1e6;int prime[MAXN+1];void IsPrime(int n){ int i, j, k; int half = n/2; int sn = sqrt(n+0.5); memset(prime, 0, sizeof(prime)); for (i = 0; i < half; i++) prime[i] = 1; // 初始化全部奇数为素数。prime[0]对应3,即p[i]对应2*i+3 for (i = 0; i < sn; i++) if(prime[i]) // 如果 2*i+3 是素数 { for(k=i+i+3,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 prime[j] = 0; } //prime[i]=1代表 2*i+3 是素数 //比如3是素数,按3*3,3*5,3*7...的次序筛选,因为只保存奇数,所以不用删3*4,3*6....}
这里给一道有关素数的题目,HDOJ:1262,时空转移(点击打开链接),题目如下:
寻找素数对
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8227 Accepted Submission(s): 4110
Problem Description
哥德巴赫猜想大家都知道一点吧.我们现在不是想证明这个结论,而是想在程序语言内部能够表示的数集中,任意取出一个偶数,来寻找两个素数,使得其和等于该偶数.
做好了这件实事,就能说明这个猜想是成立的.
由于可以有不同的素数对来表示同一个偶数,所以专门要求所寻找的素数对是两个值最相近的.
做好了这件实事,就能说明这个猜想是成立的.
由于可以有不同的素数对来表示同一个偶数,所以专门要求所寻找的素数对是两个值最相近的.
Input
输入中是一些偶整数M(5<M<=10000).
Output
对于每个偶数,输出两个彼此最接近的素数,其和等于该偶数.
Sample Input
20 30 40
Sample Output
7 1313 1717 23
题意:
中文的,就不说了,注意答案求得是值最接近的两个素数。
分析:
数据的范围是10000,那么我们就可以先使用筛法判出10000以内的所有素数,然后从m/2开始枚举,保证两个素数的值最接近。
源代码:
#include <cstdio>#include <cmath>#include <cstring>const int MAXN = 1e6;int vis[MAXN+1];int prime[MAXN+1];void IsPrime(int n){ int i, j; int m = sqrt(n+0.5); memset(vis, 0, sizeof(vis)); memset(prime, 0, sizeof(prime)); for(i=2; i<=m; ++i) if(!vis[i]) { prime[i] = 1; for(j=i*i; j<=n; j+=i) vis[j] = 1; } for(; i<=n; ++i) if(!vis[i]) prime[i] = 1;}int main(){ int m; IsPrime(10000); while(~scanf("%d", &m)) { int tmp = m/2; while(tmp >= 2) { if(prime[tmp] && prime[m-tmp]) { printf("%d %d\n", tmp, m-tmp); break; } --tmp; } } return 0;}
其他有关素数的题目还有,HDOJ:1431,2098。
接下来我们将讨论反素数,传送门(点击打开链接)。
0 0
- ACM-判素数
- 判素数
- 判素数
- 判素数(质数)
- 【入门】判素数
- 判素数(Prime number)
- 【1011】判素数
- ACM-素数
- acm素数
- 【HDU4910】高效判大素数
- VIJOS 1128 DFS+MR 判素数
- 快速判素数——Miller Rabin
- 用渣渣的方法判素数,笑哭
- poj 1581 [ acm 判题模拟]
- 计算几何:线段判交模板--ACM
- ACM 判断素数
- ACM之判断素数
- acm-素数新做
- 第一次笔试经历
- linux文件系统——读书笔记
- Android 读取APK签名信息
- css布局几个问题
- 文档的倒排 invertDocument方法的源代码
- ACM-判素数
- struts2学习笔记
- HTML5移动开发之路(12)——HTML5中的音频
- 黑马程序员--java线程
- Android 仿大众点评团购购买条浮动效果
- UVA 10192 - Vacation
- java解析xml汇总
- 如何运行python脚本 及 如何在脚本中输入中文
- String类的实现