演算法 Miller Robbin素數判定

2022-08-22 04:03:17 字數 1749 閱讀 1500

目錄

三、小結

我們以前都是怎麼判斷素數的呢:

試除法:若乙個正整數n為合數,則存在乙個能整除n的數k,其中\(2\leqslant k \leqslant \sqrt n\)。

具體實施如下:

inline int is_prime(int n)

return 1;

}

這種方法的時間複雜度為\(o(\sqrt n)\)。

現在,我們希望更快地判斷乙個數是否為素數。

我們可以借助費馬小定理來判斷:

如果p是乙個質數,而整數a不是p的倍數,則有

\[a^\equiv 1\pmod p

\]miller-robbin素數判定就是基於上述定理實現的,如果我們隨機列舉乙個\(a\),且\(a\)滿足費馬小定理,那麼\(p\)就是素數。所以miller-robbin素數判定是一種隨機性演算法。

需要注意的是,我們這樣判斷素數的方法實際上利用的是費馬小定理的逆定理。不幸的是,費馬小定理的逆定理並不是乙個真命題。

我們把像341這樣的數稱作偽素數。實際上,偽素數有無窮多組。

這意味著一次判斷不足以保證我們的程式正確。當然,解決這個問題也十分簡單。

我們只需要重複操作大約30次,便能將正確率提公升到我們期待的水平。

另外,我們使用快速冪來計算\(a^\)。總複雜度為\(o(logn)\)。

下面給出miller-robbin素數判定的模板:

int qpow(int a,int b,int mod)

return res;

}bool query_prime(int x)

return true;

}

判斷乙個正整數是否為素數
模板題:at807 素數、コンテスト、素數

#include#define int long long

using namespace std;

inline int qpow(int a,int b,int mod)

return res;

}inline int miller_robbin(int num)

return 1;

}signed main()

miller_robbin(num)?printf("yes\n"):printf("no\n");

return 0;

}

附贈一道水題:(主要是練習素數判定)

at1476 素數判定

#include#define ll long long

using namespace std;

ll qpow(ll a,ll b,ll mod)

return res;

}bool query_prime(ll x)

return true;

}int main()

使用miller-robbin素數判定,我們可以將複雜度降低至\(o(logn)\)級別(常數階可以被忽略)。這樣比原來的方法會快很多。

演算法訓練 素因子去重

題目鏈結 問題描述 給定乙個正整數n,求乙個正整數p,滿足p僅包含n的所有素因子,且每個素因子的次數不大於1 分析 之前寫了需要判斷是素數 雖然通過了 後面發現是不需要判斷的。因為當你每次去掉乙個素因子後,這個因子的倍數就會不存在了。這個和素數篩選差不多,只不過素數篩選是標記,這裡是刪除。因為i從最...

演算法訓練 素因子去重

傳送門 url 題目 問題描述 給定乙個正整數n,求乙個正整數p,滿足p僅包含n的所有素因子,且每個素因子的次數不大於1 輸入格式 乙個整數,表示n 輸出格式 輸出一行,包含乙個整數p。樣例輸入 樣例輸出 資料規模和約定 n 10 12 樣例解釋 n 1000 2 3 5 3,p 2 5 10 思路...

演算法訓練 素因子去重

時間限制 1.0s 記憶體限制 256.0mb 問題描述 給定乙個正整數n,求乙個正整數p,滿足p僅包含n的所有素因子,且每個素因子的次數不大於1 輸入格式 乙個整數,表示n 輸出格式 輸出一行,包含乙個整數p。樣例輸入 樣例輸出 資料規模和約定 n 10 12 樣例解釋 n 1000 2 3 5 ...