·判斷n是否為素數系列·
阿新 • • 發佈:2018-12-13
例題
這裡 n 的範圍都是 1e9
一:普通版O(sqrt(n))
i 從 2 到 sqrt(n) ,一個一個 判斷,是不是 n 的因數,
稍微優化一下,當 i > 2 時,只需要判斷 i 是奇數的情況。
bool isprime(int n) { int t = sqrt(n); if(n == 2 || n == 3) return true; for(int i = 2; i <= t; i++) { if(i > 2 && (i&1) == 0) continue; if(n%i == 0) return false; } return true; }
二:豪華版 O(sqrt(n) / 3)
實際做題的話要更快
經過觀察,所有的素數都分佈在 6 的倍數 兩側 (2 ,3 除外)。
所以 (n % 6 != 1) &&( n % 6 != 5) 的 一定不是素數。
當然滿足條件的也可能不是素數~~~(這裡的判斷證明還不明白。。。。)
bool isprime(int n) { if(n == 2 || n == 2) return true; if(n%6 != 1 && n%6 != 5) return false; int t = sqrt(n); for(int i = 5; i <= t; i+=6) { if(n%i == 0 || n%(i+2) == 0) return false; } return true; }
三:尤拉篩打表 O( n )
注意這裡的 O( n ) ,的 n 是打表的長度,比如,找出 1~n 的 所有素數,
顯然,n 為 1e9 的話是不可能打表的,就算能也是會超時的,
如果用尤拉篩來判斷一個 1e9 的數是否是素數,只需要大概打表到 3e4 就可以了!!!!!!!
因為:
任意一個數 n 都可以表示成若干質數的乘積,所以對於一個 1e9 的數 n ,先求出1~sqrt( 1e9 ) 的所有質數
( sqrt( 1e9 ) = 31628 )
再用 n 一個一個與這些質數比較 , 如果這些質數中沒有 n 的因數, 那麼 n 一定是一個質數!
因為 1~sqrt(n) 中沒有 n 的質因數的話,> sqrt(n) 中一定沒有 n 的因數。
typedef long long LL;
const int MAXN = 31628;
int prm[MAXN+1],vis[MAXN+1], cnt = 0;
void init()
{
for(int i = 2; i <= MAXN; i++)
{
if(!vis[i]) prm[cnt++] = i; // 沒有被標記的就是素數
for(int j = 0; j < cnt; j++)
{
LL t = i*prm[j];
if(t > MAXN) break;
vis[t] = 1; //素數的倍數也就是合數被標記
//當i能整除prime[j],那麼 i*prime[j+1] 這個合數之後肯定被 prime[j] 乘以某個數篩掉。
//避免一個數被重複篩選
if(i%prm[j] == 0)
break;
}
}
return ;
}
bool isprime(int n)
{
if(n <= MAXN)
{
if(vis[n] == 0) return true;
return false;
}
else
{
for(int i = 0; i < cnt; i++)
{
if(n%prm[i] == 0)
return false;
}
}
return true;
}