題目大意: 給定兩個數,要求産生這兩個數之間的所有質數。
兩個數位m和n,其範圍如下:
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n (1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
看似簡單的題目,其實也不簡單,一般的質數判斷方法是,看這個數n能否被2到根号n之間的數除盡,如果不能,那麼就是質數,當然,這裡這麼寫程式是會逾時的。
查表方法也不行,如果先産生所有的質數表,那麼記憶體太大了,不能儲存。一般現在都使用區間剔除的方法。
目前我知道的本題最快的就是二次區間剔除的方法了:
1 先産生2到32000(32000的平方大于1E9)之間的質數,作為一個質數表(增加這個質數表也是為了加速)
2 再産生n到m之間的所有質數
如何産生質數表? 這都是用到往前搜尋,剔除不符合條件的數,避免過多的重複計算,帶點動态規劃的味道。
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
class PrimeNumberGenerator
{
const static int MAX_NUM = 32000;
int PRIMES[MAX_NUM];
int segPrimes[100000];
public:
PrimeNumberGenerator()
{
memset(PRIMES, 0, sizeof(PRIMES));
int j = 0;
for (int i = 2; i < MAX_NUM; i++)
{
if (!PRIMES[i])
{
PRIMES[j++] = i;
for (int k = i*2; k < MAX_NUM; k+=i)//不是k++注意
{//寫成 k = i+1,頭痛錯誤!!!
PRIMES[k] = 1;
}
}
}
PRIMES[j++] = MAX_NUM;
}
//本題不需使用的函數
bool isPrimeNum(int num)
{
if (2 == num) return true;
int i = 0;
for ( ; PRIMES[i] * PRIMES[i] <= num && num % PRIMES[i]; i++);
return MAX_NUM != PRIMES[i] && num % PRIMES[i] != 0;
}
void getSegPrimes(int a, int b)
{
memset(segPrimes, 0, sizeof(segPrimes));//每一次都需要memset
for (int i = 0; PRIMES[i]*PRIMES[i] <= b; i++)//錯誤寫成i <= b-a
{
int am = a/PRIMES[i];
for (int d = am; d * PRIMES[i] <= b; d++)
{
if (d > 1 && d * PRIMES[i] >= a) segPrimes[d*PRIMES[i]-a] = 1;
}//這裡不能少了判斷條件d>1
}
}
void judgePrimes()
{
int a = 0, b = 0;
int T = 0;
cin>>T;
while (T--)
{
cin>>a>>b;
if (a < 2) a = 2;
getSegPrimes(a, b);
for (int i = a ; i <= b; i++)
{
if (0 == segPrimes[i-a]) cout<<i<<endl;
}
cout<<endl;
}
}
};
int main()
{
PrimeNumberGenerator pri;
pri.judgePrimes();
return 0;
}