数论——乘法逆元(快速幂求法)及模运算

1、快速幂ios

原理:spa

  快速幂的原理十分简单。code

  ak=a2^0*a2^1*a2^2*…a2^x,其中k=20+21+22+…+2xblog

  这显然是正确的。由于任何一个数均可以表示成二进制。get

  接下去利用位运算实现便可。it

代码实现io

  模板题连接:快速幂模板

  代码模板以下:时间复杂度O(logk)class

int qmi(int a,int k,int p) { int res=1%p; while(k) { if(k&1)res=(long long)res*a%p; a=(long long)a*a%p; k>>=1; } return res; }

  值得一提的是,以上代码在过程当中取模,是基于模运算的运算规则。stream

  模运算有一些很好的性质,如下列举四条:

  •  (a + b) % p = (a % p + b % p) % p 
  •  (a - b) % p = (a % p - b % p + p) % p 
  •  (a * b) % p = (a % p * b % p) % p 
  •  (a^b) % p = ((a % p)^b) % p 

2、快速幂求逆元

乘法逆元的定义

 若整数b,m互质,而且b|a,则存在一个整数x,使得a/bax(mod m),则称x为b的模m乘法逆元,记为b1(mod m)

b存在乘法逆元的充要条件是b与模数m互质。当模数m为质数时,bm2即为b的乘法逆元。

  由于在模运算中,并无除法的性质,即没有(a/b)%p≠((a%p)/(b%p))%p,而乘法逆元即可以帮助咱们将其转化成乘法形式:a/b % m=ax % m。

  由乘法逆元的定义咱们能够推出以下结论:

∵ a/b mod p = a * b-1 mod p = a/b * b * b-1 mod p

∴ b * b-1 ≡ 1(mod p)

费马小定理

若p是一个质数,且整数a不是p的倍数(a与p互质),则有a p-1 ≡ 1(mod p)。

  基于这个定理,咱们就能够推出以下结论:

 ∵ a p-1 ≡ 1(mod p)

∴ a * a p-2 ≡ 1(mod p)

  所以,结合乘法逆元的定义所获得的推论以及费马小定理,咱们能够获得:a-1 = a p-2(mod p)。

  也就是说,当模数p为质数,且整数b不是p的倍数时(b与p互质),b的逆元即为b p-2

代码实现

  模板题连接:快速幂求逆元  

  根据上述结论,要判断b关于模数p的乘法逆元是否存在,若存在则求出之,咱们便只须要计算b p-2便可。而这个计算利用快速幂即可以很快解决。

  代码以下:

#include <iostream> #include <algorithm> #include <cstdio>
using namespace std; typedef long long ll; int qmi(int a,int k,int p) { int res=1%p; while(k) { if(k&1)res=(ll)res*a%p; a=(ll)a*a%p; k>>=1; } return res; } int main() { int n;scanf("%d",&n); for(int i=1;i<=n;i++) { int a,b; scanf("%d%d",&a,&b); if(a%b==0)printf("impossible\n"); else printf("%d\n",qmi(a,b-2,b)); } return 0; }

应用

  有了乘法逆元,咱们在计数类问题中遇到(a/b)%p时,即可以转化成((a % p) * (b-1 % p)) % p来计算了,这样便防止了爆int的状况出现,固然,转化的前提是必须保证b与p互质。当p是质数时,则能够进一步转化为((a % p) * (b p-2 % p)) % p。

相关文章
相关标签/搜索