MR素性探測

2021-09-25 17:30:18 字數 3467 閱讀 1641

mr演算法全稱是miller-rabin測試,是乙個非確定的演算法,用於判斷乙個數是否是質數.雖然是乙個非確定的演算法,但是只要巧妙地選取引數,在一定範圍內就是乙個確定性的演算法.

前置條件:費馬小定理1 ≡ a^(p-1) (mod p)

miller和rabin兩個人的工作讓fermat素性測試邁出了革命性的一步,建立了傳說中的miller-rabin素性測試演算法。 新的測試基於下面的定理(二次探測定理):如果p是素數,x是小於p的正整數,且x^2 mod p = 1,那麼要麼x=1,要麼x=p-1。這是顯然的,因為x^2 mod p = 1相當於p能整除x^2-1,也即p能整除(x+1)(x-1)。由於p是素數,那麼只可能是x-1能被p整除(此時x=1)或x+1能被p整除(此時 x=p-1)。

這就 是miller-rabin素性測試的方法。不斷地提取指數n-1中的因子2,把n-1表示成d*2^r(其中d是乙個奇數)。那麼我們需要計算的東西就 變成了a的d*2^r次方除以n的餘數。於是,a^(d * 2^(r-1))要麼等於1,要麼等於n-1。如果a^(d * 2^(r-1))等於1,定理繼續適用於a^(d * 2^(r-2)),這樣不斷開方開下去,直到對於某個i滿足a^(d * 2^i) mod n = n-1或者最後指數中的2用完了得到的a^d mod n=1或n-1。這樣,fermat小定理加強為如下形式:

盡可能提取因子2, 把n-1表示成d*2^r,如果n是乙個素數,那麼或者a^d mod n=1,或者存在某個i使得a^(d*2^i) mod n=n-1 ( 0<=i如果你每次都用前7個素數(2, 3, 5, 7, 11, 13和17)進行測試,所有不超過341 550 071 728 320(即3.4e14)的數都是正確的。如果選用2, 3, 7, 61和24251作為底數,那麼10^16內唯一的強偽素數為46 856 248 255 981(即4.6e13)。

注意是當取模為1時才能繼續降冪取模,取模為n-1時演算法終止(但是之後的演算法實際上不是這麼死板地實現的).

ll quick_multiply

(ll a, ll b, ll c)

//快速積(和快速冪差不多)

return ans;

}ll quick_power

(ll a, ll b, ll c)

//快速冪,這裡就不贅述了

return ans;

}bool miller_rabin

(ll n,

int a, ll d)

//判斷素數

ll t =

quick_power

(a, d, n)

;while

((d != n -1)

&&(t !=1)

&&(t != n -1)

)return

(t == n -1||

(d &1)

==1);

}bool isprime

(ll n)

;for

(int i =

0; i <10;

++i)

}return true;

}

給你乙個p,乙個a,問p是不是基於a的偽素數.

偽素數是指根據費馬小定理判斷是素數的,實際上卻不是素數的數.

這題的解法很顯然,就是先用費馬小定理判斷一下是不是,再真正地判斷一下是不是.而真正的判斷的話,很多題解上給出的是暴力判斷,我們就以此當做mr素性測試的模板題吧.

費馬小定理前文提到了,但是在實際過程中發現了一點問題:

如果根據1 ≡ a^(p-1) (mod p),居然會wa,但是如果根據p ≡ a^(p) (mod p),就能過.這實在是匪夷所思,之後再深入**.

#include

using namespace std;

#define rd(x) (rand()%(x))

typedef

long

long ll;

int prime=

;ll quick_multiply

(ll a, ll b, ll c)

//快速積(和快速冪差不多)

return ans;

}ll quick_power

(ll a, ll b, ll c)

//快速冪,這裡就不贅述了

return ans;

}bool miller_rabin

(ll n,

int a, ll d)

//判斷素數

ll t =

quick_power

(a, d, n)

;// 這個迴圈運用了一些技巧,

// 盡可能提取因子2, 把n-1表示成d*2^r

// 如果n是乙個素數,

// 那麼或者a^d mod n=1,

// 或者存在某個i使得a^(d*2^i) mod n=n-1 ( 0<=i// 迴圈的次數應該是r,也就是初始的時候d移除後面連續的所有0,最後再迴圈裡一次一次挪回來

// 如果d又重新變成了n-1,那麼說明迴圈終止

// 此處的t就是a^(d*2^i) mod n ( 0<=i// 還有一種可能是a^d mod n == 1

// 這種情況只會發生在第一次迴圈中,所以如果是因為t==1而跳出迴圈,則需要判斷d是否是奇數

// 因為只有在迴圈的第一輪(d為奇數),t==1才能認為是n是質數的證據

while

((d != n -1)

&&(t !=1)

&&(t != n -1)

)return

(t == n -1||

(d &1)

==1);

}bool isprime

(ll n)

;for

(int i =

0; i <10;

++i)

}return true;

}int

main()

bool f1 =

isprime

(p);

bool f2 =

quick_power

(n, p, p)

== n;

// 此處實在是匪夷所思 寫成 n^(p-1) == 1 (mod p) 就會wa,但是這樣寫就沒問題

if(f1)

else

if(f2)

else

}return0;

}

Miller Rabin素性測試與二次探測

首先是一些概念 利用二次探測定理,只需要探測s次就可以將錯誤率降到2 s 好像是這樣吧。反正很低就對了 因此也不會多花多少時間。記得判素時的細節處理以及快速冪取模。應該是最簡潔的模板了。include using namespace std typedef long long ll ll prime...

費馬小定理(MR素數探測法) v2 0

include include include include using namespace std typedef long long ll ll powermod ll a,ll b,ll n bool witness ll a,ll n ll x powermod a,m,n if x 1 ...

Miller Rabin素性測試

博主鏈結 隨機素數測試 偽素數原理 call bool res miller n 快速測試n是否滿 足素數的 必要 條件,出錯概率極低 對於任意奇數n 2和正整數s,演算法出錯概率 2 s include include define ll long long int define met a me...