[关闭]
@nlogn 2018-12-01T10:46:26.000000Z 字数 2790 阅读 689

洛谷P3383题解

题目描述

如题,给定一个范围,你需要处理个某数字是否为质数的询问(每个数字均在范围内)

输入输出格式

输入格式

第一行包含两个正整数,分别表示查询的范围和查询的个数。
接下来行每行包含一个的整数,即询问该数是否为质数。

输出格式

输出包含行,每行为,即依次为每一个询问的结果。

INPUT & OUTPUT 's example

Input's eg #1

  1. 100 5
  2. 2
  3. 3
  4. 4
  5. 91
  6. 97

Output's eg #1

  1. Yes
  2. Yes
  3. No
  4. No
  5. Yes

说明

时空限制:
数据规模:
对于30%的数据:
对于100%的数据:

样例说明:

,说明接下来的询问数均不大于且不小于
所以为质数,非质数。
故依次输出Yes、Yes、No、No、Yes

分析

先来看一下素数的定义:

质数定义为在大于的自然数中,除了和它本身以外不再有其他因数。
————By 百度百科

所以就诞生了最简单的筛素数的方法:
我们对于传入的枚举到,每个数取模一下,从而判断是不是素数。

  1. bool is_prime(int n){
  2. if(n==1) return false;
  3. if(n==2) return true;
  4. for(register int i=2;i<=n-1;i++){
  5. if(n%i==0) return false;
  6. }
  7. return true;
  8. }

这种做法的时间复杂度为,显然,当甚至更大的时候,肯定就会到飞起。
本做法得分:
qwq记录

通过几次尝试之后,我们可以发现,因数总是成对以为轴成轴对称,所以:
我们对于传入的,只需从枚举到即可。

  1. bool is_prime(int n);{
  2. if(n==1) return false;
  3. if(n==2) return true;
  4. for(register int i=2;i<=sqrt(n);i++)
  5. if(n%i==0) return false;
  6. return true;
  7. }

上述程序时间复杂度为,大大减少了程序的复杂度。
本做法得分:
qwq记录

那么,还能够继续优化吗?

当然可以!

刚学的时候,唐只讲到优化,sb的我就以为这是最快的了。
直到,看到了,某太阳:%3462^&sdh234>>>>dkfjlw
的一通哔哩哔哩筛法,嗯。。。。
证明:摘自质数判定方法
证明:令,将大于等于的自然数表示如下:

可以看到,不在的倍数两侧,即两侧的数为由于,
所以它们一定不是素数,再除去本身,显然,素数要出现只可能出现在的相邻两侧。
所以,基于以上条件,我们假如要判定的数为,则必定是的形式,对于循环中其中如果能被整除,则至少得是一个偶数,
但是的形式明显是一个奇数,故不成立;另外,如果能被整除,则至少能被整除,
但是能被整除,故(即)不可能被整除,故不成立。综上,循环中只需要考虑的情况
即循环的步长可以定为,每次判断循环变量的情况即可,代码如下:

  1. bool is_prime(int n)
  2. {
  3. if(n==1) return false;
  4. if(n==2||n==3) return true;
  5. if(n%6!=1&&n%6!=5) return false;
  6. for(register int i=5;i*i<=n;i+=6)
  7. if(n%i==0||n%(i+2)==0) return false;
  8. return true;
  9. }

理论上述程序的时间复杂度约为
本做法得分:当然是
qwq记录

代码实现

  1. /* Headers */
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<cmath>
  5. /* define */
  6. #define MAXN 100010
  7. using namespace std;
  8. namespace FastIO{
  9. const int BUFSIZE=(1<<20);
  10. char ibuf[BUFSIZE],*is=ibuf,*it=ibuf;
  11. char obuf[BUFSIZE],*os=obuf,*ot=obuf+BUFSIZE;
  12. inline char getch(){
  13. if(is==it)
  14. it=(is=ibuf)+fread(ibuf,1,BUFSIZE,stdin);
  15. return (is==it)?EOF:*is++;
  16. }
  17. inline int getint(){
  18. int res=0,neg=0,ch=getch();
  19. while(!(isdigit(ch)||ch=='-')&&ch!=EOF)
  20. ch=getch();
  21. if(ch=='-'){
  22. neg=1;ch=getch();
  23. }
  24. while(isdigit(ch)){
  25. res=(res<<3)+(res<<1)+(ch-'0');
  26. ch=getch();
  27. }
  28. return neg?-res:res;
  29. }
  30. inline void write(int x){
  31. if(x<0)x=-x,putchar('-');
  32. if(x>10)write(x/10);
  33. putchar(x%10+'0');
  34. }
  35. inline void space(int x){
  36. if(x==0)putchar(' ');
  37. else putchar('\n');
  38. }
  39. }
  40. using namespace FastIO;
  41. /* definitions */
  42. int N,m,q;
  43. /* functions */
  44. bool is_prime(int n){
  45. if(n==1) return false;
  46. if(n==2||n==3) return true;
  47. if(n%6!=1&&n%6!=5) return false;
  48. for(register int i=5;i*i<=n;i+=6)
  49. if(n%i==0||n%(i+2)==0) return false;
  50. return true;
  51. }
  52. int main(int argc,char *argv[]){
  53. scanf("%d%d",&N,&m);
  54. for(int i=1;i<=m;i++){
  55. scanf("%d",&q);
  56. if(is_prime(q)){
  57. printf("Yes\n");
  58. }
  59. else{
  60. printf("No\n");
  61. }
  62. }
  63. return 0;
  64. }

THE END

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注