zoukankan      html  css  js  c++  java
  • 有关求质数的思考

    求出1n之间的质数

    先写了一个暴力判断的n^(3/2)的算法,虽然加了强力的优化但还是不出意外的挂了。

    试试删选

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<math.h>
    
    int ans[1000005];
    int flag[1000005];
    
    int count(int n)
    {
        ans[1]=ans[0]=0;
        int i, j;
        // 素数数量统计
        int count=0;
        // 初始化素数标记,要高效点咯
        flag[2]=1;
        for (i=3; i<n; i++)
        {
            //flag[i]=(i%2!=0)?1:0;//偶数直接值0,奇数值1,2特殊处理,但是这个有判断操作,效率肯定没有直接赋值快,所以用下面的
            flag[i++]=1;
            flag[i]=0;
        }
        // n为奇数
        if (n%2!=0) flag[n]=1;
        // 从3开始filter,因为2的倍数早在初始化时代就干掉了
        for (i=3; i <= sqrt((double)n); i++)
        {
        // i是合数,请歇着吧,因为您的工作早有您的质因子代劳了
            if (0 == flag[i]) continue;
        // 从i的平方倍开始过滤,而不是从前面的已经被其他素数筛掉了,另外变乘法为加法,加法效率比乘法快
            for (j=i*i; j <= n; j+=i) flag[j]=0;
        }
        // 统计素数个数
        for (i=2; i<=n; i++)
        {
            if (flag[i]) count++; ans[i]=count;
        }
        return count;
    }
    
    int main()
    {
        int n,maxn=2,i;
        for (i=2; i<=1000000; i++) ans[i]=1;
        count(1000000);
        while (scanf("%d",&n))
        {
            printf("%d
    ",ans[n]);
        }
        return 0;
    }

    好吧,又超时了。看来还是需要想更好的方法……

    各种找方法之后,我终于从这个博客:

    https://blog.csdn.net/code_pang/article/details/7880245

    找到了非常强大的方法。这个结论是什么呢?结论就是,如果一个数是素数(大于5),那么它必然在6x的两侧,x为正整数,两侧是指这个数字是6x-1或者6x+1

    现在证明:考虑6x, 6x+1, 6x+2, 6x+3, 6x+4, 6x+5=6(x+1)-1

    6x, 6x+2, 6x+3, 6x+4分别是6,2,3,2,的倍数,故必然不是素数。

    所以写出程序如下:

    #include<stdio.h>
    
    #include<string.h>
    
    #include<stdlib.h>
    
    #include<math.h>
    
     
    
    int ans[1000005];
    
    int flag[1000005];
    
    int count=0;
    
     
    
    int pan(int num)
    
    {
    
        int i;
    
        if (num==1) return 0;
    
        if (num==2 || num==3) return 1;
    
        if (num%6!=1 && num%6!=5) return 0;
    
        for (i=5; i<=sqrt(num); i+=6)
    
        {
    
            if (num%i==0 || num%(i+2)==0)//用一堆可能是素数的值判断um是不是素数
    
                return 0;
    
        }
    
        return 1;
    
    }
    
     
    
    int main()
    
    {
    
        int n,maxn=2,i;
    
        for (i=2; i<=1000000; i++) ans[i]=1;
    
        for (i=2; i<=1000000; i++)
    
        {
    
            if (pan(i)==1) count++;
    
            ans[i]=count;
    
        }
    
        //printf("%d
    ",count);
    
        while (scanf("%d",&n))
    
        {
    
            printf("%d
    ",ans[n]);
    
        }
    
        return 0;
    
    }

    你以为我会AC?对不起,这样还是不够快……于是没办法了……

    就在我把上述文字写完发布之后,我突然想到,会不是是我把读入写错了?!改了一下一看,还真是……好吧我把读入写出死循环了,应该写成!=EOF这样子。用删选法试了试,AC了……

  • 相关阅读:
    RF手持配置问题
    S4系统编辑屏幕报错
    【SAP】日志表CDHDR和CDPOS
    VA01隐藏销售凭证流的金额
    ABAP MODIFY SCREEN
    解决SMARTFORMS 中table 控件单行跨页的问题
    golang json 性能分析
    【高性能】GO 高性能专题
    9千万次循环 从2分3秒 优化到 7.3秒的过程 GO语言
    IDE 插件开发 相关点 -------------- Vscode debug protocol JDWP DAP
  • 原文地址:https://www.cnblogs.com/Shymuel/p/9100989.html
Copyright © 2011-2022 走看看