贝祖定理:若 ax + by = m 则 m 必为gcd(a,b)的若干倍,可以形象化的把 a 化为与 b 的最大公因子和另外一个因子乘积的形式,b 亦是。
欧几里得:gcd(a,b) = gcd(b,a%b) (a > b),后面将这个最小公因子表示为 GCD
首先设 a = bx + k(bx < a),因为a - bx 为 GCD倍数,而这里得 a - bx 刚好等价于 a % b,即为 k,则可知 k 也是和他们共一个最大公因子,对于这个表达还有数学形式的,网上有很多就不详细解释了。
辗转相除:设 x = 8 , y = 4 ,则他们的最大公因子为 4 ,则可知 nk 与 k 之间的最大因子是 k ,那么我们在这里套用上述论证则可知,当gcd(a,b)中,一方是另一方的倍数之后则最大公因子就确定是较小的那一方。那么我们用欧几里得的递推式,套用这个定理,则可求出最大因子,因为有一个 b 赋给 a ,a % b 赋给 b 的过程所以也俗称辗转相除。
拓展欧几里:
ax + by = k * GCD = bx1 + (a%b)y1,一般问题是找到他们的x y的通解与特解,在实际操作中,后续的这个GCD是没用的,只是好让我们清楚的知道拓展欧几里得的正确性。
在欧几里得最后得解的那一步中,我们可知道 an * xn + bn * yn 中的 an 即为原a , b 的最小公因数,bn为零,一般这个时候我们就可以设通解xn = 1 , yn = 0(当然 yn 理论上也是可以成为其他整数的,因为这个式子本身就是带有多解情况的),由于此时的an , bn 都不是原来的a 与 b ,所以这里的通解并不是实际a , b 上的通解而是满足递推式子的通解。
为了方便递推,我们将原来的推理式变形为:ax + by = bx1 + (a - a/b * b) * y1 ,当然这里的a/b向下取整,在开括号有,
bx1 + a * y1 - a/b * b * y1 = ax + by 即
ax + by = a * y1 + b * (x1 - a/b*y1) 则:
x = y1 , y = (x1 - a/b * y1),变形的原因显而易见,就是想变换出单独含有ax,by的式子顺承原式子
这样我们在递归的归状态时就能推出原结果了。
int EXGCD(int a,int b,int &x,int &y)//扩展欧几里得算法
{
if(b==0)
{
x=1;y=0;
return a; //同欧几里得,只是在最后设出通解
}
int r=EXGCD(b,a%b,x,y);//递归入口
int temp=y;
y=x-(a/b)*y;//递推式
x=temp;
return r; //返回最大因子
}