简体   繁体   English

(spoj)prime generator using c- time limited exceeded 问题?

[英](spoj)prime generator using c- time limited exceeded issue?

My code is throwing time exceeded in spoj although it is executed correctly,尽管正确执行,但我的代码在 spoj 中抛出了超时,

Here's my code:这是我的代码:

#include <stdio.h>
 
int main() {
 
    int t;
    scanf("%d",&t);
    while(t--){
        long int n,m,count=0;
        scanf("%ld%ld",&n,&m);
        for(int i=n;i<=m;i++){
            count=0;
            for(int j=1;j<=i;j++){
                if(i%j==0){
                    count++;
                }
            }
            if(count==2){
                printf("%d\n",i);
            }
        }
    }
    return 0;
}

From my top comments, there are various speedups...从我的最高评论来看,有各种加速......

  1. The biggest issue is that you iterate by 1 until you reach m .最大的问题是您迭代 1 直到到达m This is much faster if you stop at the int equivalent of sqrt(m) .如果您停在sqrt(m)的 int 等价物处,这会快得多。

  2. And, after checking for 2, you only need to test odd values, so you can do: i += 2 instead of i++ (eg 3,5,7,9,11,13,15,17,29,... ).而且,在检查 2 之后,你只需要测试奇数,所以你可以这样做: i += 2而不是i++ (例如3,5,7,9,11,13,15,17,29,... ).

  3. And, after 3, primes are numbers that are only of the form: 6n-1 or 6n+1 .并且,在 3 之后,质数是仅具有以下形式的数字: 6n-16n+1 So, you can test [only] the sequence 5,7 11,13 17,19 23,25 29,31...因此,您可以 [仅] 测试序列5,7 11,13 17,19 23,25 29,31...

thank you for showing interest to solve my doubt could u please clearly explain from point to point感谢您对解决我的疑问表现出兴趣,请您逐点清楚地解释一下好吗

There are many references for the above speedups.上述加速有很多参考资料。 For the first two, look at https://en.wikipedia.org/wiki/Trial_division对于前两个,请查看https://en.wikipedia.org/wiki/Trial_division

For (3), a web search on prime 6n produces:对于 (3),对prime 6n的 web 搜索产生:

  1. https://primes.utm.edu/notes/faq/six.html https://primes.utm.edu/notes/faq/six.html
  2. https://reflectivemaths.wordpress.com/2011/07/22/proof-primes-are-6n-1/ https://reflectivemaths.wordpress.com/2011/07/22/proof-primes-are-6n-1/

Note that [as others have mentioned], a "sieve" algorithm may be faster if you have sufficient memory: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes请注意,[正如其他人提到的那样],如果您有足够的 memory,“筛分”算法可能会更快: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes


Note that I first mentioned (1) (on SO) in a comment here: Finding Primes, where did I got wrong?请注意,我在这里的评论中首先提到了 (1)(在 SO 上): Finding Primes,我哪里错了?

I had developed a benchmark program for successively faster algorithms for that question, but never got around to adding an answer.我已经为该问题开发了一个连续更快算法的基准程序,但一直没有时间添加答案。

Here is the program that I developed.这是我开发的程序。 Note that the function prime1 is equivalent to your algorithm.请注意,function prime1等同于您的算法。

// primebnc/primebnc.c -- prime algorithm benchmark

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//#define MAXCNT        10001
//#define MAXCNT        20002
//#define MAXCNT        30003
//#define MAXCNT        40004
#define MAXCNT      1000000

int opt_f;

typedef unsigned long long val_t;

typedef struct {
    int tst_no;                         // test number
    const char *tst_who;                // test description
    double tst_elap;                    // elapsed time for test
} tst_t;

int tstnocur;                           // current test number
int tstnobase;                          // lowest test number
int tstnomax;                           // highest test number
int inited;                             // 1=initialization complete
const char *reason;
tst_t tstlist[30];                      // list of test results

int pcntold;
double bestrate;
double tvprev;

int maxcnt;
val_t *pxold;
val_t *pxnow;

// iteratively get square root
#define SQR(_n) \
    for (;  (xsqrt * xsqrt) < _n;  xsqrt += 1)

// tstloc -- find test control for given test number
tst_t *
tstloc(int tstno)
{

    if (tstno == 0)
        tstno = tstnocur;

    return &tstlist[tstno];
}

// tstset -- setup test
void
tstset(int tstno,const char *tag)
{
    tst_t *tst;

    tstnocur = tstno;

    // remember lowest test number
    if (tstnobase == 0)
        tstnobase = tstno;

    // increase count of active tests
    if (tstno > tstnomax)
        tstnomax = tstno;

    reason = tag;

    tst = tstloc(tstno);
    tst->tst_no = tstno;
    tst->tst_who = reason;
}

int
prime1(val_t *primes)
{
    val_t i;
    int idx;
    int isprime;
    val_t n = 2;

    idx = 0;
    while (idx <= maxcnt) {
        isprime = 1;

        for (i = 2; i < n; i++) {
            if (n % i == 0) {
                isprime = 0;
                break;
            }
        }

        if (isprime) {
            primes[idx] = n;
            idx++;
        }

        n++;
    }

    tstset(1,"baseline 2 to n");

    return idx;
}

int
prime2(val_t *primes)
{
    val_t i;
    int idx;
    int isprime;
    val_t xsqrt;
    val_t n = 2;
    val_t n2;

    xsqrt = 0;

    idx = 0;
    primes[idx++] = 2;

    while (idx <= maxcnt) {
        // get sqrt(n)
        SQR(n);

        isprime = 1;

        for (i = 2; i <= xsqrt; i++) {
            if (n % i == 0) {
                isprime = 0;
                break;
            }
        }

        if (isprime) {
            primes[idx] = n;
            idx++;
        }

        n2 = n + 1;
        if (n2 < n)
            printf("overflow: idx=%d\n",idx);
        n = n2;
    }

    tstset(2,"2 to sqrt by 2");

    return idx;
}

int
prime3(val_t *primes)
{
    val_t i;
    int idx;
    int isprime;
    val_t xsqrt;
    val_t n;

    xsqrt = 0;

    idx = 0;
    primes[idx++] = 2;
    primes[idx++] = 3;
    n = 5;

    while (idx <= maxcnt) {
        // get sqrt(n)
        SQR(n);

        isprime = 1;
        for (i = 3; i <= xsqrt; i += 2) {
            if (n % i == 0) {
                isprime = 0;
                break;
            }
        }

        if (isprime) {
            primes[idx] = n;
            idx++;
        }

        n += 2;
    }

    tstset(3,"3 to sqrt by 2");

    return idx;
}

int
prime4(val_t *primes)
{
    val_t i;
    int idx;
    int isprime;
    val_t xsqrt;
    val_t n;
    val_t lo;
    val_t hi;

    xsqrt = 0;

    idx = 0;
    primes[idx++] = 2;
    primes[idx++] = 3;
    n = 6;

    while (idx <= maxcnt) {
        lo = n - 1;
        hi = n + 1;

        // get sqrt(n)
        SQR(hi);

        isprime = 3;
        for (i = 3;  i <= xsqrt;  i += 2) {
            if (isprime & 1) {
                if (lo % i == 0)
                    isprime &= ~1;
            }
            if (isprime & 2) {
                if (hi % i == 0)
                    isprime &= ~2;
            }
            if (! isprime)
                break;
        }

        if (isprime & 1) {
            primes[idx] = lo;
            idx++;
        }

        if (isprime & 2) {
            primes[idx] = hi;
            idx++;
        }

        n += 6;
    }

    tstset(4,"6 to sqrt by 6 (combined 6n-1/6n+1 loops)");

    return idx;
}

int
prime5(val_t *primes)
{
    val_t i;
    int idx;
    int isprime;
    val_t xsqrt;
    val_t n;
    val_t lo;
    val_t hi;

    xsqrt = 0;

    idx = 0;
    primes[idx++] = 2;
    primes[idx++] = 3;
    n = 6;

    while (idx <= maxcnt) {
        lo = n - 1;
        hi = n + 1;

        // get sqrt(n)
        SQR(hi);

        isprime = 1;
        for (i = 3; i <= xsqrt; i += 2) {
            if (lo % i == 0) {
                isprime = 0;
                break;
            }
        }
        if (isprime) {
            primes[idx] = lo;
            idx++;
        }

        isprime = 1;
        for (i = 3; i <= xsqrt; i += 2) {
            if (hi % i == 0) {
                isprime = 0;
                break;
            }
        }
        if (isprime) {
            primes[idx] = hi;
            idx++;
        }

        n += 6;
    }

    tstset(5,"6 to sqrt by 6 (separate 6n-1/6n+1 loops)");

    return idx;
}

int
prime6(val_t *primes)
{
    int cnt;
    int isprime;
    val_t xsqrt;
    val_t n;
    val_t lo;
    val_t hi;
    val_t pval;
    val_t *pptr;
    val_t *pend;

    xsqrt = 0;

    cnt = 0;
    primes[cnt++] = 2;
    primes[cnt++] = 3;
    n = 6;

    while (cnt <= maxcnt) {
        lo = n - 1;
        hi = n + 1;

        // get sqrt(n)
        SQR(hi);

        isprime = 3;
        pptr = primes;
        pend = primes + cnt;
        for (;  pptr < pend;  ++pptr) {
            pval = *pptr;

            // early stop if we exceed square root of number being tested
            if (pval > xsqrt)
                break;

            // test 6n - 1
            if (isprime & 1) {
                if ((lo % pval) == 0)
                    isprime &= ~1;
            }

            // test 6n + 1
            if (isprime & 2) {
                if ((hi % pval) == 0)
                    isprime &= ~2;
            }

            // bug out if both are non-prime
            if (! isprime)
                break;
        }

        // 6n - 1 is prime
        if (isprime & 1) {
            primes[cnt] = lo;
            cnt++;
        }

        // 6n + 1 is prime
        if (isprime & 2) {
            primes[cnt] = hi;
            cnt++;
        }

        n += 6;
    }

    tstset(6,"6 to sqrt by prime list (combined 6n-1/6n+1 loops)");

    return cnt;
}

int
prime7(val_t *primes)
{
    int cnt;
    int isprime;
    val_t xsqrt;
    val_t n;
    val_t lo;
    val_t hi;
    val_t pval;
    val_t *pptr;
    val_t *pend;

    xsqrt = 0;

    cnt = 0;
    primes[cnt++] = 2;
    primes[cnt++] = 3;
    n = 6;

    while (cnt <= maxcnt) {
        lo = n - 1;
        hi = n + 1;

        // get sqrt(n)
        SQR(hi);

        // check for 6n - 1 is prime
        isprime = 1;
        pptr = primes;
        pend = primes + cnt;
        for (;  pptr < pend;  ++pptr) {
            pval = *pptr;

            // early stop if we exceed square root of number being tested
            if (pval > xsqrt)
                break;

            // test 6n - 1
            if ((lo % pval) == 0) {
                isprime = 0;
                break;
            }
        }
        if (isprime) {
            primes[cnt] = lo;
            cnt++;
        }

        // check for 6n + 1 is prime
        isprime = 1;
        pptr = primes;
        pend = primes + cnt;
        for (;  pptr < pend;  ++pptr) {
            pval = *pptr;

            // early stop if we exceed square root of number being tested
            if (pval > xsqrt)
                break;

            // test 6n + 1
            if ((hi % pval) == 0) {
                isprime = 0;
                break;
            }
        }
        if (isprime) {
            primes[cnt] = hi;
            cnt++;
        }

        n += 6;
    }

    tstset(7,"6 to sqrt by prime list (separate 6n-1/6n+1 loops)");

    return cnt;
}

double
tscgetf(void)
{
    struct timespec ts;
    double sec;

    clock_gettime(CLOCK_REALTIME,&ts);

    sec = ts.tv_nsec;
    sec /= 1e9;
    sec += ts.tv_sec;

    return sec;
}

void
showrat(double ratio,int tstprev)
{
    const char *tag;

    if (ratio > 1.0)
        tag = "faster";
    else {
        tag = "slower";
        ratio = 1.0 / ratio;
    }

    printf(" %.3fx %s than prime%d\n",ratio,tag,tstprev);
}

void
timeit(int (*pfnc)(val_t *))
{
    tst_t *tstcur;
    tst_t *tstcmp;
    val_t *pnow;
    val_t *pold;
    int pcntact;
    double tvbeg;
    double tvend;
    double rate;
    double ratio;

    printf("---------------\n");

    pold = pxold;
    pnow = inited ? pxnow : pxold;

    // load up the cache
    for (int i = 0; i < maxcnt; i++)
        pnow[i] = 1;

    tvbeg = tscgetf();
    pcntact = pfnc(pnow);
    tvend = tscgetf();

    tvend -= tvbeg;

    tstcur = tstloc(0);

    printf("prime%d: %s\n",tstnocur,reason);

    // show prime generation rate
    rate = (double) maxcnt / tvend;
    printf(" %.9f (%.3f primes/sec)\n",tvend,rate);

    do {
        if (! inited) {
            pcntold = pcntact;
            bestrate = rate;
            break;
        }

        // show time ratio
        for (int tstno = tstnobase;  tstno <= tstnomax;  ++tstno) {
            if (tstno == tstnocur)
                continue;
            tstcmp = tstloc(tstno);
            ratio = tstcmp->tst_elap / tvend;
            showrat(ratio,tstno);
        }

        for (int i = 0; i < maxcnt; i++) {
            if (pnow[i] != pold[i]) {
                printf("%d: pold=%lld pnow=%lld\n",i,pold[i],pnow[i]);
                break;
            }
        }
    } while (0);

    tstcur->tst_elap = tvend;
    inited = 1;
}

int
main(int argc,char **argv)
{
    char *cp;

    --argc;
    ++argv;

    maxcnt = MAXCNT;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        case 'f':
            opt_f = 1;
            break;
        case 'N':
            maxcnt = strtol(cp + 2,&cp,10);
            break;
        }
    }

    setlinebuf(stdout);

    if (opt_f)
        maxcnt = 40004;

    printf("maxcnt=%d\n",maxcnt);
    pxold = calloc(maxcnt + 1,sizeof(val_t));
    pxnow = calloc(maxcnt + 1,sizeof(val_t));

    // this takes a whole minute
    if (opt_f)
        timeit(prime1);

    // these are _much_ faster
    timeit(prime2);
    timeit(prime3);
    timeit(prime4);
    timeit(prime5);
    timeit(prime6);
    timeit(prime7);

    return 0;
}

Here is the program output with the -f option (to force invocation of prime1 ):这是带有-f选项(强制调用prime1 )的程序 output:

maxcnt=40004
---------------
prime1: baseline 2 to n
 69.242110729 (577.741 primes/sec)
---------------
prime2: 2 to sqrt by 2
 0.182171345 (219595.459 primes/sec)
 380.093x faster than prime1
---------------
prime3: 3 to sqrt by 2
 0.091353893 (437901.424 primes/sec)
 757.955x faster than prime1
 1.994x faster than prime2
---------------
prime4: 6 to sqrt by 6 (combined 6n-1/6n+1 loops)
 0.095818758 (417496.541 primes/sec)
 722.636x faster than prime1
 1.901x faster than prime2
 1.049x slower than prime3
---------------
prime5: 6 to sqrt by 6 (separate 6n-1/6n+1 loops)
 0.095270157 (419900.642 primes/sec)
 726.797x faster than prime1
 1.912x faster than prime2
 1.043x slower than prime3
 1.006x faster than prime4
---------------
prime6: 6 to sqrt by prime list (combined 6n-1/6n+1 loops)
 0.047716141 (838374.591 primes/sec)
 1451.126x faster than prime1
 3.818x faster than prime2
 1.915x faster than prime3
 2.008x faster than prime4
 1.997x faster than prime5
---------------
prime7: 6 to sqrt by prime list (separate 6n-1/6n+1 loops)
 0.040664196 (983764.685 primes/sec)
 1702.778x faster than prime1
 4.480x faster than prime2
 2.247x faster than prime3
 2.356x faster than prime4
 2.343x faster than prime5
 1.173x faster than prime6

Here is the program output without -f :这是没有-f的程序 output:

maxcnt=1000000
---------------
prime2: 2 to sqrt by 2
 24.093246222 (41505.407 primes/sec)
---------------
prime3: 3 to sqrt by 2
 12.029967308 (83125.745 primes/sec)
 2.003x faster than prime2
---------------
prime4: 6 to sqrt by 6 (combined 6n-1/6n+1 loops)
 12.633468866 (79154.824 primes/sec)
 1.907x faster than prime2
 1.050x slower than prime3
---------------
prime5: 6 to sqrt by 6 (separate 6n-1/6n+1 loops)
 12.002494335 (83316.015 primes/sec)
 2.007x faster than prime2
 1.002x faster than prime3
 1.053x faster than prime4
---------------
prime6: 6 to sqrt by prime list (combined 6n-1/6n+1 loops)
 4.346790791 (230054.780 primes/sec)
 5.543x faster than prime2
 2.768x faster than prime3
 2.906x faster than prime4
 2.761x faster than prime5
---------------
prime7: 6 to sqrt by prime list (separate 6n-1/6n+1 loops)
 3.761972904 (265817.970 primes/sec)
 6.404x faster than prime2
 3.198x faster than prime3
 3.358x faster than prime4
 3.190x faster than prime5
 1.155x faster than prime6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM