C中的素数发生器

时间:2016-05-29 18:15:52

标签: c math primes

这是问题的链接:http://www.spoj.com/problems/PRIME1/

基本上我们有两个限制,我们必须打印出它们之间的所有素数......

这是我的代码(语言== C):

#include <stdio.h>

void IsPrime(int test){
    for(int i= 2; i<test; i++){
        if(test%i==0){
            return;
        }
    }
    printf("%d\n",test);
}

int main(){
    int T,lower,upper;
    scanf("%d",&T);

    while(T--){
        scanf("%d",&lower);
        scanf("%d",&upper);

        for(int i = lower;i<=upper;i++){
            if(i>1){
            IsPrime(i);
            }
        }  
    }
return 0;
}

在我的本地机器上,我运行了它,它适用于简单的测试用例......我的网站消息是超时错误所以我想知道是否有更有效的方法来解决这个问题,因为显然我没有解决它够快吗?

3 个答案:

答案 0 :(得分:2)

首先,你不必去检查n中的每个数字,以确定n是否为素数,仅确定其平方根(有数学证明,现在不给它)。所以:

void IsPrime(int test){
    // i <= sqrt(test)
    // but to avoid sqrt you can do i * i <= test
    for(int i= 2; i * i <= test; i++){
        if(test%i==0){
            return;
        }
    }
    printf("%d\n",test);
}

接下来,我们知道在2之后,所有其他素数都是奇数,所以如果我们将2视为特例,我们可以循环2:

// Do greater than one check only once
if (lower > 1) {
    // Special case - lower is 2
    if (lower == 2) {
        printf("%d\n", 2);
        ++lower;
    }

    for(int i = lower; i <= upper; i += 2){
        IsPrime(i);
    }
}

然而,由于你必须做T次,你最终会做的比你需要的更多。此外,这个问题限制了n和m,所以它基本上适合筛子,正如@HennoBrandsma所说。

使用这些优化,您应该找到所有质数到限制,并将它们存储在容器中。然后,当提示范围时,只需移动筛子并打印出数字。

(这将要求你更多地更改IsPrime功能 - 而不是立即打印数字,让它返回true或false,然后根据它,将数字添加到容器中)

答案 1 :(得分:1)

您可以尝试以下方法,对测试次数进行略微优化,并跳过大于2的任何偶数值:

int isprime (int v)
{
    int i;

    if (v < 0) v = -v;                          /* insure v non-negative */
    if (v < 2 || !((unsigned)v & 1))    /* 0, 1 + even > 2 are not prime */
        return 0;

    if (v == 2) return 1;

    for (i = 3; i * i <= v; i+=2)
        if (v % i == 0)
            return 0;

    return 1;
}

如果您可以使用数学库和math.h,则可能会更快:

int isprime (int v)
{
    int i;

    if (v < 0) v = -v;                          /* insure v non-negative */
    if (v < 2 || !((unsigned)v & 1))    /* 0, 1 + even > 2 are not prime */
        return 0;

    if (v == 2) return 1;

    for (i = 3; i <= sqrt (v); i+=2)
        if (v % i == 0)
            return 0;

    return 1;
}

我在int范围内为两个版本定时了1-2百万之间的值,并且它们已接近。

注意:在重复调用的实际测试中,i * i <= v(下面isprime2)的版本始终比i <= sqrt (v) {{{ 1}}下面)。 e.g:

isprime3

短驱动程序迭代$ ./bin/isprimetst2 isprime (1.650138 sec) - 78497 primes isprime2 (0.805816 sec) - 78497 primes isprime3 (0.983928 sec) - 78497 primes 的所有素数,例如:

0-2000000

答案 2 :(得分:0)

您可以在C中使用库maths.h并使用sqrt函数计算给定数字的平方根。所以程序可能是这样的:

#include <stdio.h>
#include <maths.h>

int isPrime(int number){
    int i;
    if(number % 2 == 0){
        return;
    }

    for(i=3; i<=sqrt(number); i++){
        if(number % i == 0){
            return;
    }
    printf("%d\n",number);
}

int main(){
    int lower,upper,i;
    if(lower >1){
        if(lower == 2){
            printf("2\n");
        }

        for(i=lower; i<=upper; i++){
            isPrime(i);
        }
    return 0;
}

简而言之,您可以使用if-else条件来使用一些额外的检查(如if(number%2 == 0))来降低程序的时间复杂度。例如,if if条件可能是if(number%5) == 0)等,所以在这些条件的帮助下,检查不会在许多情况下进行循环,这会减少程序的时间。