有关求质数的思考

求出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\n",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\n",count);

    while (scanf("%d",&n))

    {

        printf("%d\n",ans[n]);

    }

    return 0;

}

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

 

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

posted @ 2018-05-28 16:59  竹夭公子  阅读(143)  评论(0编辑  收藏  举报