[英](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...从我的最高评论来看,有各种加速......
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 等价物处,这会快得多。
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,...
).
And, after 3, primes are numbers that are only of the form: 6n-1
or 6n+1
.并且,在 3 之后,质数是仅具有以下形式的数字:
6n-1
或6n+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 搜索产生:
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.