米勒拉賓算法的基本概念以下:ios
首先判斷這個數n的奇偶性算法
若爲偶數僅有2是質數ide
奇數則進入測試函數
測試方法:測試
首先肯定幾個基底a,範圍在[2,n-1]優化
由於n是奇數,因此n-1一定爲偶數spa
則n-1能夠表示爲(2^s)*dcode
s、d分別求出來blog
設t爲a^d模n的數,有以下幾個約定:遞歸
1.若t=-1或1時則該數n可能爲質數
2.若此時t=n-1,則該數可能爲質數
3.d*2>n-1時n必爲合數
4.若上述皆不知足則讓d*2,返回2
多組測試以後就能判斷是否爲質數,並且錯誤率至關低!!
不過想證實米勒拉賓的正確性仍是很困難的
須要費馬小定理等七七八八的數論
具體的能夠百度
我就不給於證實了~
直接上模板:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 8 ll add_mod(ll a,ll b,ll mod){ //快乘法 基於快速冪的二分思想 9 ll ans=0; //因爲考慮到取模數很大 快速冪會溢出 10 while(b){ //必須使用該方法 11 if(b&1) //我這裏寫的是非遞歸版 12 ans=(ans+a)%mod; 13 a=a*2%mod; 14 b>>=1; 15 } 16 return ans; 17 } 18 19 ll pow_mod(ll a,ll n,ll mod){ //快速冪 遞歸版 20 if(n>1){ 21 ll tmp=pow_mod(a,n>>1,mod)%mod; 22 tmp=add_mod(tmp,tmp,mod); 23 if(n&1) tmp=add_mod(tmp,a,mod); 24 return tmp; 25 } 26 return a; 27 } 28 29 bool Miller_Rabbin(ll n,ll a){//米勒拉賓素數判斷函數主體 30 ll d=n-1,s=0,i; 31 while(!(d&1)){ // 先把(2^s)*d 算出來 32 d>>=1; 33 s++; 34 } 35 ll t=pow_mod(a,d,n); //a^d取一次餘判斷 36 if(t==1 || t==-1) //一或負一則能夠聲明這多是質數 37 return 1; 38 for(i=0;i<s;i++){ //不是的話繼續乘上s個2 39 if(t==n-1) //(n-1)*(n-1)%n=1 這一步是優化 40 return 1; 41 t=add_mod(t,t,n); // 快乘 42 } 43 return 0; 44 } 45 46 bool is_prime(ll n){ 47 ll i,tab[4]={3,4,7,11};//原本應該取[1,n]內任意整數 48 for(i=0;i<4;i++){ //但通常這幾個數足以,不須要太多組測試 49 if(n==tab[i]) 50 return 1; //小判斷小優化~ 51 if(!n%tab[i]) 52 return 0; 53 if(n>tab[i] && !Miller_Rabbin(n,tab[i])) 54 return 0; 55 } 56 return 1; 57 } 58 59 int main(){ 60 ll n; 61 scanf("%lld",&n); 62 if(n<2) printf("No"); 63 else if(n==2) printf("Yes"); 64 else{ 65 if(!n%2) printf("No"); 66 else if(is_prime(n)) 67 printf("Yes"); 68 else printf("No"); 69 } 70 return 0; 71 }