【数论】Miller_Rabin、线性求逆元

typedef long long LL;

Miller_Rabin素数测试

二次探测定理

如果 p p p是素数, x x x是小于 p p p的正整数,且 x 2 ≡ 1 ( m o d p ) x^2\equiv1\pmod p x21(modp),那么要么 x = 1 x=1 x=1,要么 x = p − 1 x=p-1 x=p1
解读: 因为 x 2 m o d    p = 1 x^2\mod p=1 x2modp=1,即 p ∣ x 2 − 1 p|x^2-1 px21,也即 p ∣ ( x + 1 ) ( x − 1 ) p|(x+1)(x-1) p(x+1)(x1)
由于 p p p是素数且 x < p x<p x<p,那么只可能是 x − 1 x-1 x1能被 p p p整除(此时 x = 1 x=1 x=1)或 x + 1 x+1 x+1能被 p p p整除(此时 x = p − 1 x=p-1 x=p1)。

要测试整数 n n n是否为素数,若 n n n是素数,根据费马定理,有 a n − 1 m o d    n = 1 a^{n-1}\mod n=1 an1modn=1
首先任选一个数做底数 a a a
我们令 n − 1 = d ⋅ 2 R n-1=d\cdot 2^R n1=d2R,其中 d d d是一个奇数,于是 a n − 1 m o d    n = ( a d ) 2 R m o d    n = a d ⋅ 2 R − 1 ⋅ a d ⋅ 2 R − 1 m o d    n a^{n-1}\mod n=(a^d)^{2^R}\mod n=a^{d\cdot 2^{R-1}}\cdot a^{d\cdot 2^{R-1}}\mod n an1modn=(ad)2Rmodn=ad2R1ad2R1modn
根据二次探测定理, a d ⋅ 2 R − 1 m o d    n a^{d\cdot 2^{R-1}}\mod n ad2R1modn要么等于 1 1 1要么等于 n − 1 n-1 n1
如果 a d ⋅ 2 R − 1 m o d    n a^{d\cdot 2^{R-1}}\mod n ad2R1modn既不等于 1 1 1也不等于 n − 1 n-1 n1 n n n一定不是素数,结束讨论。
如果 a d ⋅ 2 R − 1 m o d    n = n − 1 a^{d\cdot 2^{R-1}}\mod n=n-1 ad2R1modn=n1,我们认为 n n n是素数,结束讨论。
如果 a d ⋅ 2 R − 1 m o d    n = 1 a^{d\cdot 2^{R-1}}\mod n=1 ad2R1modn=1,继续讨论:

  • 根据二次探测定理, a d ⋅ 2 R − 2 m o d    n a^{d\cdot 2^{R-2}}\mod n ad2R2modn要么等于 1 1 1要么等于 n − 1 n-1 n1。……

上述讨论过程中,如果存在某个整数 k k k,使得 a d ⋅ 2 k m o d    n = n − 1 ( 0 ⩽ k < R ) a^{d\cdot 2^k}\mod n = n-1 (0\leqslant k<R) ad2kmodn=n1(0k<R),我们就认为 n n n是素数,结束讨论。
或者,若 a d m o d    n = 1 a^d\mod n=1 admodn=1 n n n是素数。

这是一种不确定算法,每一次测试的准确率约为 75 % 75\% 75%
若进行了 m m m次测试,时间复杂度为 O ( m log ⁡ 3 n ) O(m\log_3n) O(mlog3n)

bool miller_rabin(LL n){
  if(n==2)return 1;
  if(n<2||!(n%2))return 0;
  LL d=n-1;int r=0;
  while(!(d&1))d/=2,r++;
  for(int i=1;i<=10;i++){
    LL a=rand()%(n-2)+2,x=Pow(a,d,n);
    for(int j=1;j<=r;j++){
      LL y=Mul(x,x,n);
      if(y==1&&x!=1&&x!=n-1)return 0;
      x=y;
    }
    if(x!=1)return 0;
  }
  return 1;
}

一些玄学操作:

  • n < 4759123141 n<4759123141 n<4759123141时,只需检测 a = 2 , 7 , 61 a=2,7,61 a=2,7,61,即可确保正确。
  • n < 2152302898747 n<2152302898747 n<2152302898747时,只需检测 a = 2 , 3 , 5 , 7 , 11 a=2,3,5,7,11 a=2,3,5,7,11,即可确保正确。
  • n < 341550071728320 n<341550071728320 n<341550071728320时,只需检测 a = 2 , 3 , 5 , 7 , 11 , 13 , 17 a=2,3,5,7,11,13,17 a=2,3,5,7,11,13,17,即可确保正确。

线性求逆元

a − 1 = { 1 a = 1 ( p − ⌊ p a ⌋ ) ( p m o d    a ) − 1 m o d    p a > 1 a^{-1}=\begin{cases} 1&a=1\\ (p-\lfloor\frac pa\rfloor)(p\mod a)^{-1}\mod p&a>1 \end{cases} a1={1(pap)(pmoda)1modpa=1a>1

证明:
显然 1 1 1的逆元为 1 1 1
a > 1 a>1 a>1时,已知 a ⋅ a − 1 ≡ 1 ( m o d p ) a\cdot a^{-1}\equiv 1\pmod p aa11(modp),其中 1 < a < p 1<a<p 1<a<p
k = ⌊ p a ⌋ , r = p m o d    a k=\lfloor\frac pa\rfloor,r=p\mod a k=ap,r=pmoda,那么 p = k a + r , 0 < r < a p=ka+r,0<r<a p=ka+r,0<r<a
则有 k a + r ≡ 0 ( m o d p ) ka+r\equiv 0\pmod p ka+r0(modp)
两边同时乘以 a − 1 r − 1 a^{-1}r^{-1} a1r1得到 ( k a + r ) a − 1 r − 1 ≡ 0 ( m o d p ) (ka+r)a^{-1}r^{-1}\equiv 0\pmod p (ka+r)a1r10(modp)
k ⋅ r − 1 + a − 1 ≡ 0 ( m o d p ) k\cdot r^{-1}+a^{-1}\equiv 0\pmod p kr1+a10(modp)
转换得
a − 1 = − k ⋅ r − 1 m o d    p = − ⌊ p a ⌋ ( p m o d    a ) − 1 m o d    p = ( p − ⌊ p a ⌋ ) ( p m o d    a ) − 1 m o d    p \begin{aligned} a^{-1}&=-k\cdot r^{-1}\mod p\\ &=-\lfloor\frac pa\rfloor(p\mod a)^{-1}\mod p\\ &=(p-\lfloor\frac pa\rfloor)(p\mod a)^{-1}\mod p \end{aligned} a1=kr1modp=ap(pmoda)1modp=(pap)(pmoda)1modp

时间复杂度: O ( n ) O(n) O(n)

void make_inv(int*inv,int n,int p){
  inv[1]=1;
  for(int i=2;i<=n;i++)inv[i]=(p-p/i)*inv[p%i]%p;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值