简单数论(五)------Miller Rabin 素数判定
本来简单数论5准备写高斯消元的但是咕掉了,所以简单数论5改成了素数判定,高斯消元之后直接补到(四)里面
简单数论(五)------Miller Rabin 素数判定
PartI 素数判定
如果现在给你一个数N,你要怎样判断他是否是素数,显然我们可以直接枚举1-sqrt(N)的数能否整除N,如果可以一定是合数
但这样的时间复杂度很不优秀
这时就要用到Miller Rabin算法了
PartII 前置知识---费马小定理和二次探测
(1):费马小定理:若P是质数,且(a,p)=1,ap-1≡1 (mod P)
(2): 二次探测:对于素数P,能够满足x2≡1 (mod P)的同余类x只有x≡1 (mod P)和x≡p-1 (mod P)
PartIII 算法流程(对于N)
(1):筛掉偶数
(2):找到一个最大的s使得2s*t=N-1
(3):随机选取质数a,我们先算出 ,然后不断地平方并且进行二次探测(进行 次)。
#include<bits/stdc++.h> using namespace std; inline int read() { int f=1,x=0; char ch; do { ch=getchar(); if(ch=='-') f=-1; }while(ch<'0'||ch>'9'); do { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); }while(ch>='0'&&ch<='9'); return f*x; } typedef long long ll; ll n; ll p[12]={2,3,5,7,11,13,17,19,23,29,31,37}; inline ll Pow(ll a,ll b,ll c) { ll ans=1,mul=a; while(b) { if(b&1) { ans*=mul; ans%=c; } mul*=mul; mul%=c; b>>=1; } return ans%c; } inline bool Miller_Rabin(ll x) { if(x==1){ return false; } if(x==2) return true; if(x%2==0) return false; bool f=1; for(ll i=0;i<12;i++) { if(p[i]==x) return true; ll t=x-1,s=0; while(t%2==0){ t/=2; s++; } ll cur=Pow(p[i],t,x); if(cur==1) continue; for(ll j=1;j<=s;j++) { ll nxt=cur*cur%x; if(nxt==1&&cur!=1&&cur!=x-1) { f=0; break; } cur=nxt; if(cur==1) break; } if(cur!=1) f=0; if(!f) break; } return f; } int main() { n=read(); if(Miller_Rabin(n)) { cout<<"IS PRIME"<<endl; } else cout<<"NOT PRIME"<<endl; }