如何提高超出时限的速度

时间:2015-06-13 03:13:57

标签: c++ c performance

有没有办法改善这个程序的运行时间?我从在线评判中获得超出时间限制的错误,似乎我的程序运行缓慢? 所以,这是该计划的问题:http://www.spoj.com/problems/PRIME1/

我的代码(语言c):

#include <stdio.h>

void FindPrime (int m, int n)
{
    int i, prime = 1;

    if (m <= n)
    {
        for (i = m - 1; i > 1; i--)
        {
            if (m % i == 0)
            {
                prime = 0;
                break;
            }
        }
        if (prime == 1 && m != 1)
            printf ("%d\n", m);
        FindPrime (m + 1, n);
    }
}

int main ()
{
    int num1, num2, i, cases;

    scanf ("%d", &cases);
    while (cases != 0)
    {
        scanf ("%d %d", &num1, &num2);
        FindPrime (num1, num2);
        printf ("\n");
        cases--;
    }

    return 0;
}

2 个答案:

答案 0 :(得分:0)

要解决这个问题,您需要学习“Eratosthenes的筛子”

  1. 首先,从here了解它的工作原理。但是,这还不足以解决这个问题。因为,算法的复杂性是O(n.log(log(n)))。因此,如果我们把 n = 1000000000 。它肯定无法执行。

  2. 现在,时间来优化它。从here阅读。但是,我们已经完成了。

  3. (完成上述两项后请阅读本节)因为我们要找到素数是 [m,n] 的范围。因此,首先使用Eratosthenes( sqrt(10 ^ 9)= 31622.7 的筛子,在2到32000的范围内创建一个素数列表(让我们称之为 primeList ),这小于32000)。现在,检查 [m,n]

    范围内的每个数字 k

    3.1。如果数字 k 2-32000 的范围内,则该数字位于 primeList 中。打印出来。

    3.2。如果数字 k &gt; 32000,并且可被&lt; = sqrt(k)以及 primeList 中的所有数字整除。打印出来。否则,忽略或不打印它。 (记住它'1'不是素数)。

  4. 您可以查看我的solution。但是,虽然所应用的概念是相同的,但它的实现与我解释的略有不同。

答案 1 :(得分:0)

你的代码计算/列出数字m和amp之间的素数。 n个案例次数。现在你的算法花费O(n)时间用于m&amp;的每个值。因此,您的代码对单个案例所花费的总时间是O(nxm)或O(n ^ 2)倍。总共花费的时间是* O(n ^ 2)..这很糟糕。使用一些更好的算法,以减轻复杂性.. 检查此 Sieve of Eratosthenes

的修改版本
#include <stdio.h>
#define SIZE (int)(sizeof(boolean) / sizeof(int))
int main(){
  int up,low;
  int i,j;
  printf("\nEnter the upper limit: ");
  scanf("%d", &up);
  printf("\nEnter the lower limit: ");
  scanf("%d", &low);

  int boolean[up];
  int list[up];

  for(i = 0; i < SIZE; i++){
  boolean[i] = 1;
  list[i] = 2 + i;
  }

  for(i = 0; i <= up; i++){
    if (boolean[i] == 1)
     for(j = i +1; j < SIZE; j++)
       if(list[j] % list[i] == 0)
       boolean[j] = 0; 

  }

  for(i = 0; i < SIZE; i++)
   if(boolean[i] == 1 && list[i] >= low && list[i] <= up)
   printf("%d ", list[i]);
printf("\n");

return 0;
}

这不会多次访问一个号码。因此会降低对数刻度的复杂性。