对a,b求最大公因数
我们显然可以对a,b进行因式分解,然后将公共因数相乘
1035=32 · 5 · 23
759=3 · 11 · 23
gcd(1035,759)=3 · 23=69
但是我们还没有有效进行因式分解的算法,这时候我们可以使用Euclid最大公因数算法
-
注
-
GCD可以指:最大公因数(greatest common divisor,简写为gcd)
a ÷ b ① a除以b ② b除a
gcd(a,b)=1,a,b互质
Euclid算法:求最大公因数
Euclid规则:如果x和y都是正整数,且x≥y,那么gcd(x,y) = gcd(x mod y , y)
-
证明上述结论成了,只需证明gcd(x,y) = gcd(x -y , y)
-
① 辗转相除法:两个整数的最大公约数等于其中较小的数和两数的差的最大公约数 => gcd(x,y) = gcd(x -y , y) 【这里又牵涉到了辗转相除法的证明,哈哈,不证了】
② 然后,不断减y gcd(x,y) = gcd(x -y , y) = gcd(x -y-y , y) = gcd(x -y-y -y , y)= … = gcd(x mod y , y)
C++实现:
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b, a%b); //记住这里反着的,两边交换 mod
}
Euclid扩展: 求逆元以便除法求模
如何求逆元,使用Euclid扩展算法
规则 1: bb1 % N = 1 称 b1是关于 b % N的乘法逆元
规则 2:如果d 整除 a和b,同时存在整数x和y,使得d=ax+by,那么d=gcd(a,b)
证明
① d 是 a 和 b 的公因数 : d ≤ gcd(a,b)
② gcd(a,b) 能够整除 d=ax+by :d ≤ gcd(a,b)
d = gcd(a,b)
bb1 % N = 1
等价于 bx + Ny =1
,运用到Euclid算法求出 x 就是 b 的逆元
伪代码
EuclidEx(int a,int b)
{
if(b=0): return (1,0,a)
(x',y',d)=EuclidEx(b,a mod b)
return (y' , x-⌊a/b⌋y',d)
}
何来:d=gcd(a,b)=gcd(b, a mod b)=b x’ + (a mod b)y’ =bx’ +(a - ⌊a/b⌋b)y’ = a y’
+ b( x-⌊a/b⌋y’
)
得出 -7×47+11×30=1
C++ 实现
#include <iostream>
using namespace std;
void EuclidEx(int a, int b,int &x,int &y)
{
// ax+by=1 output x,y
if (b == 0) { x = 1; y = 0; return; }
EuclidEx(b, a %b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
}
int main()
{
int x; int y;
EuclidEx(47, 30, x, y);
cout << x;
}
求 :47-1 mod 30 即 47x+30y=1;
得出:
除法求模
我们都见过加减乘求模,那么除法求模呢?
(a ÷ b)%p=?
若 bb1 % N = 1
—>(a ÷ b) % p = ab1 % N
一旦除法求模,我们需要知道被除数的逆元
-7 mod 30 = 23