目录
分数取模
费马小定理
费马小定理:若p为素数/质数,则有ap-1≡1 (mod p)
逆元法
求解逆元
乘法逆元
每个数a均有唯一的与之对应的乘法逆元x,使得ax≡1(mod n) , 一个数有逆元的充分必要条件是gcd(a,n)=1,即a与n互素,此时逆元唯一存在 。
逆元的含义:模n意义下,一个数a如果有逆元x,那么除以a相当于乘以x。
扩展欧几里得算法
欧几里得算法
定理与证明
欧几里得算法又称辗转相除法,用于计算两个非负整数a,b的最大公约数。
定理:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数,也即gcd(a,b) = gcd(b,a mod b) (不妨设a>b 且r=a mod b ,r不为0)
证明:设正整数a、b且a>b,令a=kb+r,其中k为正整数,0<r<b,即r=a%b,设d为a和b的一个公约数,记作d|a和d|b,即a和b都可以被d整除
对于r=a-kb,两边同时除以d,r/d=a/d-kb/d,可知a/d-kb/d为整数,故r/d也是整数,故有d|r,又r即为a%b,所以d也是b与a%b的公约数,故有gcd(a,b) = gcd(b,a mod b)
代码实现
Java版
//递归
int gcd(int a,int b){
if(!a) return m;
int r = b%a;
return gcd(n,r);
}
//非递归
int gcd(int a,int b){
int temp;
while(a){
temp=b%a;
b=a;
a=temp;
}
return b
}
Python版
def gcd(a, b):
while a:
a, b = b % a, a
return b
代码中的a和b不区分大小,无论a和b谁大,都能返回正确的结果
扩展欧几里得算法
原理
算法实现
Python
def ex_gcd(a,b):
if a == 0 and b == 0: # 0与0没有最大公约数,因为任何非零数都能整除0
return None
else:
x1, y1, x2, y2 = 1, 0, 0, 1 # 初始化x1,y1,x2,y2
while b:
q, r = divmod(a, b)
a, b = b, r # 求最大公约数
# 矩阵乘法,即上述②式左边化简的过程
x1, y1, x2, y2 = x2, y2, x1 - q * x2, y1 - q * y2
# 若传入的 a,b 是负数,那么最后结果有可能为负,需要取负
return (a, x1, y1) if a > 0 else (-a, -x1, -y1)
求逆元
假定求整数a在模数26下的逆元
在ax + by = gcd(a,b)中,不妨令b为26,也即ax + 26y = gcd(a,26)
当gcd(a,26)为1时,有(ax + 26y )%26= gcd(a,26)%26,也即ax%26=1%26,故x%26即为整数a在模数26下的逆元
Python版
def inv(a,p):
g, x , y = ex_gcd(a, p)
if g != 1:
return 0 #表示整数a没有逆元
return x % p
费马小定理
费马小定理:若p为素数/质数,则有ap-1≡1 (mod p)
推理:ap-2 * a≡ 1 (mod p),即 ap-2就是a在模p意义下的逆元
欧拉定理:若a、p互素,则有 aφ(p) ≡ 1 (mod p),(费马小定理的一般形式)
推理: aφ(p)-1 * a ≡ 1 (mod p),即aφ(p)-1 就是 a在模p 意义下的逆元