1. 程式人生 > >·判斷n是否為素數系列·

·判斷n是否為素數系列·

例題

這裡 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;
}