0

スフィア オンライン ジャッジ(SPOJ) でいくつかのチャレンジを行っていますが、制限時間内に2 つ目の問題(プライム ジェネレーター) を実行できないようです。次のコードの速度を上げるにはどうすればよいですか?

#include <stdio.h>
#include <math.h>

int is_prime(int n);
void make_sieve();
void fast_prime(int n);

int primes[16000];

int main()
{
    int nlines;
    int m, n;
    make_sieve();
    scanf("%d", &nlines);
    for (; nlines >= 1; nlines--) {
        scanf("%d %d", &m, &n);
        if (!(m % 2)) {
            m++;
        }
        for ( ; m < n; m+=2) {
            fast_prime(m);
        }
        printf("\n");
    }
    return 0;
}

/* Prints a number if it's prime. */
inline void fast_prime(int n)
{
    int j;
    for (int i = 0; ((j = primes[i]) > -1); i++) {
        if (!(n % j)) {
            return;
        }
    }
    printf("%d\n", n);
}

/* Create an array listing prime numbers. */
void make_sieve()
{
    int j = 0;
    for (int i = 0; i < 16000; i++) {
        primes[i] = -1;
    }
    for (int i = 2; i < 32000; i++) {
        if (i % 2) {
            if (is_prime(i)) {
                primes[j] = i;
                j++;
            }
        }
    }
    return;
}

/* Test if a number is prime. Return 1 if prime. Return 0 if not. */
int is_prime(int n)
{
    int rootofn;
    rootofn = sqrt(n);
    if ((n <= 2) || (n == 3) || (n == 5) || (n == 7)) {
        return 1;
    }
    if (((n % 2) == 0) || ((n % 3) == 0) || ((n % 5) == 0) || ((n % 7) == 0)) {
        return 0;
    }
    for (int i = 11; i < rootofn; i += 2) {
        if ((n % i) == 0) {
            return 0;
        }
    }
    return 1;
}
4

2 に答える 2

2

isprime() は、素数テーブル primes[] を使用しません。

さらに、バイナリ検索アルゴリズムを使用して迅速に完了する素数配列の検索を実装します。標準ライブラリには 1 つ含まれています。

コードのどこに時間が費やされているかを確認するには、プロファイリング gcc の例を使用できます

gcc -p -g - o mycode mycode.c
===run the code--
gprof mycode
于 2010-05-29T09:57:04.580 に答える
1

現在、あなたの問題は時間制限ではありません。あなたのプログラムは決して数字を出力しないという事実です。

最も明らかなエラーは、fast_prime で、n が素数 [0]、素数 [1]、... 素数 [k] で割り切れるかどうかをチェックしていることです。n が素数であっても、n は素数 [] のどこかにあるため、出力しません。そのため、n は何らかの数で割り切れます...

これを修正するには、n が n の平方根までの素数で割り切れることを確認する必要があります (これには、コードを高速化するという副作用もあります。これは、いくつかの数が素数であると判断する前にチェックされる数が少なくなるためです。 )

fast_prime を変更します

inline void fast_prime(int n)
{    
  int j;
  int rootofn;
  rootofn = sqrt(n);        
  for (int i = 0; ((j = primes[i]) > -1) && (j<rootofn); i++) {
      if (!(n % j)) {
          return;
      }
  }
  printf("%d\n", n);
}
于 2010-05-29T09:33:31.830 に答える