區(qū)間素?cái)?shù)線性篩選

區(qū)間素?cái)?shù)線性篩選

假設(shè)應(yīng)用場(chǎng)景為求一個(gè)區(qū)間長度遠(yuǎn)小于右端點(diǎn)的所有素?cái)?shù),該區(qū)間為 [l, r] 。如若使用樸素素?cái)?shù)線性篩選,則需要的時(shí)間復(fù)雜度為 T(r)=rln(lnr) , 如果使用區(qū)間素?cái)?shù)線性篩選算法,則需要的時(shí)間復(fù)雜度為 T(r)=\sqrt{r} ln(ln \sqrt{r}) .

思想

首先使用樸素素?cái)?shù)線性篩選算法獲得 [1, \sqrt{r}] 的素?cái)?shù)集合 \Omega , 然后利用該集合的素?cái)?shù) p_ik 倍篩掉區(qū)間 [l, r] 的合數(shù),其中
k = max(2, \lceil\frac{l}{p_i}\rceil)

時(shí)間復(fù)雜度

設(shè)篩選區(qū)間為 [l, r] 的所有素?cái)?shù)。則由算法的特性可知,對(duì)于每個(gè)素?cái)?shù) p_i ,均要篩掉 \lfloor\frac{r-l}{p_i}\rfloor 個(gè)合數(shù), 若區(qū)間的長度遠(yuǎn)小于區(qū)間右端點(diǎn),則算法的時(shí)間復(fù)雜度花費(fèi)主要在 [1, \sqrt{r}] 的素?cái)?shù)篩選上。

則總的時(shí)間復(fù)雜度為

T(r) = \sum_{p_i=2}^{\sqrt{r}}{\frac{r-l}{p_i}}=\sqrt{r}ln(ln\sqrt{r}),p_i\ is\ prime.

即在該應(yīng)用場(chǎng)景下,可以以 \sqrt{n} 的復(fù)雜度獲得該區(qū)間內(nèi)的所有素?cái)?shù)

代碼部分:

using array_int = vector<int>;
using array_int_ref = array_int &;
using array_bool = vector<bool>;
using array_bool_ref = array_bool &;

/***
樸素素?cái)?shù)線性篩選算法
**/
void regular_sieve(array_int_ref array, const int size) {
    // 使用sqrt(size)大小的素?cái)?shù)來進(jìn)行篩選,進(jìn)行優(yōu)化
    const int sqrt_size = sqrt(size) + 1;

    // 使用標(biāo)記數(shù)組進(jìn)行標(biāo)記是否為素?cái)?shù)
    array_bool is_prime(size + 1, true);
    for (int i = 2; i <= sqrt_size; ++i) {
        if (is_prime[i]) {

            // 使用i*i,進(jìn)行優(yōu)化
            for (int j = i * i; j <= size; j += i) {
                is_prime[j] = false;
            }
        }
    }

    // 清空無效數(shù)據(jù)
    array.clear();

    // 將標(biāo)記為素?cái)?shù)的數(shù)收集起來
    for (int i = 2; i <= size; ++i) {
        if (is_prime[i]) {
            array.push_back(i);
        }
    }
}

/***
區(qū)間素?cái)?shù)篩選算法
**/
void segment_sieve(array_int_ref array, const int l, const int r) {
    // 清空無效數(shù)據(jù)
    array.clear();

    // 判斷輸入范圍是否有效
    if (l > r) {
        return;
    }

    // 先使用樸素的線性素?cái)?shù)篩選算法,獲得[1, sqr(n)+1]內(nèi)的所有素?cái)?shù)
    const int sqrt_size = sqrt(r) + 1;
    const int total = r - l + 1;
    array_int sqrt_array;
    regular_sieve(sqrt_array, sqrt_size);

    // 利用樸素線性素?cái)?shù)篩選算法所獲得的素?cái)?shù)集合,篩選[l, r]內(nèi)的素?cái)?shù)集合
    array_bool is_prime(total + 1, true);
    for (int i = 0; i < sqrt_array.size(); ++i) {
        const auto& p = sqrt_array[i];

        // 獲取在區(qū)間[l, r]內(nèi)最小k_min倍p的合數(shù)c_min,k_min最小為2,
        int k_min = max(2, (l / p) + (l % p == 0 ? 0 : 1));
        int c_min = k_min * p;

        // 將區(qū)間[l, r]映射到[0, total-1],篩掉區(qū)間內(nèi)的合數(shù)
        for (int j = c_min - l; j < total; j += p) {
            is_prime[j] = false;
        }
    }

    // 將區(qū)間[0, total-1]所標(biāo)記的素?cái)?shù)映射到[l, r]內(nèi),并將素?cái)?shù)添加到array數(shù)組
    for (int i = 0; i < total; ++i) {
        if (is_prime[i]) {
            array.push_back(i + l);
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容