逆元的理解 
数论中的逆元即数论倒数,既一个正整数a,存在另一个正整数x使得a × x ≡ 1 ( m o d     p ) a\times x≡1(\mod p) a × x ≡ 1 ( m o d p )  (其中a与p互素),则称x为a的一个关于p的逆元。
  逆元的由来 
为什么要有逆元这个说法呢,类比到矩阵中去,在矩阵乘法中,两个乘积为单位矩阵的矩阵,其中一个矩阵就是另一个矩阵的逆矩阵,这样就解决了矩阵中没有定义除法的问题。
而类似的,在数论中也没有除法的相关定义(学过线代会知道整数集对于除法是不封闭的),于是我们就思考如何将乘法转换为除法(参考实数集中的分数)。
再来举几个取模中的例子来说明一下:
再取模运算的规律中,有如下几个定义:
( a + b ) m o d     p = ( a m o d     p + b m o d     p ) m o d     p (a +  b) \mod p = (a\mod p +  b\mod p) \mod p ( a + b ) m o d p = ( a m o d p + b m o d p ) m o d p 
( a − b ) m o d     p = ( a m o d     p − b m o d     p ) m o d     p (a  -  b) \mod p = (a\mod p  -  b\mod p) \mod p ( a − b ) m o d p = ( a m o d p − b m o d p ) m o d p 
$(a  \times  b) \mod p = (a\mod p \times  b\mod p) \mod p $
为什么其中没有定义除法相关的取模运算呢?
来举个例子
对于( 100 / 50 ) m o d     20 (100/50)\mod 20 ( 1 0 0 / 5 0 ) m o d 2 0  来说,结果应该是2;
那么如果使用上述定义的方法来计算这个值,也就是( ( 100 m o d     20 ) / ( 50 m o d     20 ) ) m o d     20 ((100\mod 20) /(50\mod 20))\mod 20 ( ( 1 0 0 m o d 2 0 ) / ( 5 0 m o d 2 0 ) ) m o d 2 0  , 
那么结果应该是0,显然是矛盾的,也就是说对于除法来说,取模运算时非常复杂的,而在计算机中,通常需要计算两个很大的数字相除的时候,是存不下的,但这个时候又不能使用取模公式使分子和分母变小,于是就有了逆元
  逆元的概念 
在实数集中我们如何将除法转化为乘法呢,我们定义了分数,也就是
若a × x = 1 a\times x=1 a × x = 1  ,就令x = 1 / a x=1/a x = 1 / a  ,如果a不为1,x就为小数。
而在数论中要考虑的问题就变成了a × x ≡ 1 ( m o d     p ) a\times x≡1(\mod p) a × x ≡ 1 ( m o d p )  ,而这里的x还是1/x嘛?答案是不是,举个例子:
2 × 3 m o d     5 = 1 2\times 3\mod 5=1 2 × 3 m o d 5 = 1 
所以逆元也叫数论倒数。这里我们令x = i n v ( a , p ) x=inv(a,p) x = i n v ( a , p )  ,也就是表示a模p运算时的逆元。
那么我们再来思考这个问题( a / b ) m o d     p (a/b)\mod p ( a / b ) m o d p  要如何来转化,我们先将除法变为乘法,也就是( a × i n v ( a , p ) ) m o d     p (a\times inv(a,p))\mod p ( a × i n v ( a , p ) ) m o d p  。
于是我们就能使用乘法公式进行展开,变为( a m o d     p × i n v ( a , p ) m o d     p ) m o d     p (a\mod p\times inv(a,p)\mod p)\mod p ( a m o d p × i n v ( a , p ) m o d p ) m o d p  ,于是我们缩小a的目的就达到了。
下面介绍如何计算逆元
  逆元的计算 
首先明确只有当a与p互质时,a才存在关于p的逆元。求逆元的方法主要时利用费马小定理和拓展欧几里得定理
  费马小定理 
  证明 
数论四大定理中的费马小定理是这样定义的:
a p − 1 ≡ 1 ( m o d     p ) a^{p-1}≡1(\mod p) a p − 1 ≡ 1 ( m o d p )  ,其中p为素数,a与p互素。
那么我们两边同时乘以a关于p的逆元,也就得到了a p − 1 × i n v ( a , p ) ≡ i n v ( a , p ) ( m o d     p ) a^{p-1}
\times inv(a,p)≡inv(a,p)(\mod p) a p − 1 × i n v ( a , p ) ≡ i n v ( a , p ) ( m o d p ) 
于是由逆元的性质得到了逆元的计算方法:
a p − 2 ≡ i n v ( a , p ) ( m o d     p ) a^{p-2}≡inv(a,p)(\mod p) a p − 2 ≡ i n v ( a , p ) ( m o d p ) 
也就是a p − 2 = i n v ( a , p ) ( m o d     p ) a^{p-2}=inv(a,p)(\mod p) a p − 2 = i n v ( a , p ) ( m o d p )  ,再使用一次快速幂就能得到逆元了
  代码 
1 2 3 4 5 6 7 8 9 10 11 12 LL pow_mod (LL a, LL b, LL p)  {    LL ret = 1 ;     while (b){         if (b & 1 ) ret = (ret * a) % p;         a = (a * a) % p;         b >>= 1 ;     }     return  ret; } LL Fermat (LL a, LL p)  {        return  pow_mod (a, p-2 , p); } 
 
  拓展欧几里得算法 
当a,b互质的时候,贝祖定理得到的结果应该是长这样的:
a × x + b × y = 1 a\times x+b\times y=1 a × x + b × y = 1 
贝祖定理证明了这个式子是有解的。接下来我们让两边同时取模b,得到:
a × x m o d     b + b × y m o d     b = 1 m o d     b a\times x\mod b+b\times y\mod b=1\mod b a × x m o d b + b × y m o d b = 1 m o d b 
也就是
a × x m o d     b = 1 m o d     b a\times x\mod b=1\mod b a × x m o d b = 1 m o d b 
于是得到同余方程:
a × x ≡ 1 ( m o d     b ) a\times x≡1(\mod b) a × x ≡ 1 ( m o d b ) 
于是x就是inv(a,b)。于是就能通过拓展欧几里得算法,求出x。
  代码 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <cstdio>  typedef  long  long  LL;void  ex_gcd (LL a, LL b, LL &x, LL &y, LL &d)  {    if  (!b) {d = a, x = 1 , y = 0 ;}     else {         ex_gcd (b, a % b, y, x, d);         y -= x * (a / b);     } } LL inv (LL t, LL p)  {    LL d, x, y;     ex_gcd (t, p, x, y, d);     return  d == 1  ? (x % p + p) % p : -1 ; } int  main ()  {    LL a, p;     while (~scanf ("%lld%lld" , &a, &p)){         printf ("%lld\n" , inv (a, p));     } } 
 
  参考链接 
境外之主