【学习笔记】Miller-Rabin(米勒-拉宾)素性测试,附常用表
@TOC
素性測試是檢驗一個給定的整數是否為素數的測試。
最簡單的就是用 n\sqrt{n}n? 以內的數去試除。這是確定性的算法,即能準確知道 nnn 是否為質數。
但今天學習的是一種隨機算法。
Fermat 小定理
如果 ppp 是一個質數,且 a%p≠0a\%p≠0a%p?=0,則有 ap?1≡1(modp)a^{p-1}\equiv 1\pmod pap?1≡1(modp)
利用 Fermat定理 可以得到一個測試合數的有力算法:對 n>1n>1n>1,選擇 a>1a>1a>1, 計算 an?1modna^{n-1} \mod nan?1modn。
-
若結果 ≠1\neq 1?=1,則 nnn 是合數。
-
若結果 =1=1=1, 則 nnn 可能是素數,并被稱為一個以 aaa 為基的弱可能素數 (a-PRP) 。
若 nnn 是合數,則又被稱為一個以 aaa 為基的偽素數。
這個算法的成功率是相當高的。在 <25000000000<25000000000<25000000000 的 109198740510919874051091987405 個素數中,一共只有 218532185321853 個以 222 為基的偽素數。
但不幸的是,存在無窮多個被稱為 Carmichael數(卡邁克爾數)的整數,對于任意與其互素的整數 aaa 算法的計算結果都是 111。
最小的五個 Carmichael數 是 561、1105、1729、2465、2801561、1105、1729、2465、2801561、1105、1729、2465、2801 。
miller_rabin(米勒-拉賓)素性測試
定理 :如果 ppp 是個 >2>2>2 的質數,則方程 x2≡1(modp)x^2\equiv 1\pmod px2≡1(modp) 的解只有 x=±1x=±1x=±1。
證明:
x2≡1(modp)?x2?1≡0(modp)?(x+1)(x?1)≡0(modp)x^2\equiv 1\pmod p\Rightarrow x^2-1\equiv 0\pmod p\Rightarrow (x+1)(x-1)\equiv 0\pmod px2≡1(modp)?x2?1≡0(modp)?(x+1)(x?1)≡0(modp)
若 p∣(x+1)∧p∣(x?1)p|(x+1)\wedge p|(x-1)p∣(x+1)∧p∣(x?1)。則一定存在兩個數 j,kj,kj,k,使得 x+1=jp,x?1=kpx+1=jp,x-1=kpx+1=jp,x?1=kp,兩式相減 2=(k?j)p2=(k-j)p2=(k?j)p,不可能。
所以只可能是 p∣(x+1)∨p∣(x?1)p|(x+1)\vee p|(x-1)p∣(x+1)∨p∣(x?1)。
設 p∣(x+1)p|(x+1)p∣(x+1),則 x+1=kp?x≡?1(modp)x+1=kp\Rightarrow x\equiv -1\pmod px+1=kp?x≡?1(modp)
設 p∣(x?1)p|(x-1)p∣(x?1),則 x?1=kp?x≡1(modp)x-1=kp\Rightarrow x\equiv 1\pmod px?1=kp?x≡1(modp)
以上定理的逆否命題:當方程 x2≡1(modp)x^2\equiv 1\pmod px2≡1(modp) 有一個解 x≠?1∧x≠1x\neq-1\wedge x\neq 1x?=?1∧x?=1,則 ppp 一定不是質數。
miller_rabin 是一個質數判斷算法,采用隨機算法能夠在很短的時間里判斷一個數是否是質數.
如何將卡邁克爾數甄別出來,這里要用到 二次探測方法。
算法流程:
-
設 ppp 是要判斷的數,222 特判后,ppp 如果是質數必須是奇數
-
將 p?1p-1p?1 分解為 2r?k2^r*k2r?k,則有 ap?1=(ak)2ra^{p-1}=(a^k)^{2^r}ap?1=(ak)2r
-
可以先求出 aka^kak,然后將其不斷平方,并取模 ppp
-
對于任意的 0<a<p0<a<p0<a<p,有 ak≡1(modp)a^k\equiv 1\pmod pak≡1(modp),或者 a2s?k≡?1(modp),0≤s<ra^{2^s*k}\equiv-1\pmod p,0\le s<ra2s?k≡?1(modp),0≤s<r。
只要有一個等式成立,那么后面不斷平方結果也是 111,在代碼實現時就會立即跳出。
如果一個都沒有成立則說明一定不是個質數。
但是當 ppp 為合數的時候,也可能會騙過檢測,這就是“偽素數”。
如果挑選多個不同的 aaa 來檢測,那么就會降低騙過的概率。
這也就是 miller_rabin 要多次操作的原因。
容錯率是 14c\frac{1}{4}^c41?c,取決于操作次數 ccc。
在競賽中,用固定的幾個數就夠了,附表。
| 2047 | 2 |
| 1373653 | 2,3 |
| 9080191 | 31,73 |
| 25326001 | 2,3,5 |
| 4759123141 | 2,7,61 |
| 1122004669633 | 2,3,13,1662803 |
| 2152302898747 | 2,5,7,11 |
| 3474749660383 | 2,5,7,11,13 |
| 341550071728321 | 2,3,5,7,11,13,17 |
| 3825123056546413051 | 2,3,5,7,11,13,17,19 |
HDU2138
#include <cstdio> using namespace std; #define int long long int test[5] = { 2, 3, 61 };int qkpow( int x, int y, int mod ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }bool dfs( int n, int a, int d ) {if( n == a ) return 1;if( ! ( n & 1 ) ) return 0;while( ! ( d & 1 ) ) d >>= 1;int x = qkpow( a, d, n );while( d ^ ( n - 1 ) and x ^ 1 and x ^ ( n - 1 ) ) {x = x * x % n;d <<= 1;}return x == n - 1 or ( d & 1 ); }bool isprime( int n ) {if( n == 2 ) return 1;for( int i = 0;i < 2;i ++ ) if( ! dfs( n, test[i], n - 1 ) ) return 0;return 1; }signed main() {int T, n;while( ~ scanf( "%lld", &T ) ) {int sum = 0;for( int i = 1;i <= T;i ++ ) {scanf( "%lld", &n );if( isprime( n ) ) sum ++;}printf( "%lld\n", sum );}return 0; }總結
以上是生活随笔為你收集整理的【学习笔记】Miller-Rabin(米勒-拉宾)素性测试,附常用表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [WF2011] MachineWork
- 下一篇: 怎么查询域名注册时间(怎么查网站域名注册