目錄
三、小結
我們以前都是怎麼判斷素數的呢:
試除法:若乙個正整數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 ...