GCD

GCD-欧几里得定理(辗转相除)

Elements

(GCD(a,b)=GCD(b,a\%b))

Confirmation

(a=bk+c),显然有(c=a\%b)。设(d|a d|b),则

[c=a-bk ]

[frac{c}{d}=frac{a}{d}-frac{b}{d}k ]

由右边的式子可知(frac{c}{d})为整数,即(d|c)所以对于(a,b)的公约数,它也会是(a\%b)的公约数。

反过来也需要证明

(d|b d|(a\%b)),我们还是可以像之前一样得到以下式子

[frac{a\%b}{d}=frac{a}{d}-frac{b}{d}k ]

[frac{a\%b}{d}+frac{b}{d}k=frac{a}{d} ]

因为左边式子显然为整数,所以(frac{a}{d})也为整数,即(d|a),所以(b,a\%b)的公约数也是(a,b)的公约数。

既然两式公约数都是相同的,那么最大公约数也会相同

所以得到式子

[gcd(a,b)=gcd(b,a\%b) ]

Code

所以我们可以写出一个递归式,层层深入,直到 (b%(a%b)==0),即正好为倍数整除时,递归回去就行了

int gcd(int a,int b)
{
	if(b==0)
    	return a;
    return gcd(b,a%b);
}

最后的返回值自然为(a,b)的最大公因数

EXGCD-扩展欧几里得定理

目的:求(ax+by=gcd(a,b))的一组可行解
证明

[ax_1+by_1=gcd(a,b) ]

[bx_2+(a\,mod\,b)y_2=gcd(b,a\,mod\,b) ]

由欧几里得定理可知:

[gcd(a,b)=gcd(b,a\,mod\,b) ]

所以

[ax_1+by_1=bx_2+(a\,mod\,b)y_2 ]

又因为

[a\,mod\,b=a-(lfloorfrac{a}{b} floor*b) ]

所以

[ax_1+by_1=bx_2+(a-(lfloorfrac{a}{b} floor*b))y_2 ]

[ax_1+by_1=ay_2+bx_2-lfloorfrac{a}{b} floor*by_2=ay_2+b(x_2-lfloorfrac{a}{b} floor y_2) ]

因为(a=a,b=b),所以

[x_1=y_2 ]

[y_1=x_2-lfloorfrac{a}{b} floor y_2 ]

(x_2,y_2)不断代入递归求解直至(GCD)为0递归(x=1,y=0)回去求解,就像(GCD)一样的方法

int Exgcd(int a,int b,int &x,int &y)
{
    if (!b) 
    {
        x=1;y=0;
        return a;
    }
    int d=Exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-(a/b)*y;
    return d;
}

返回的值为(GCD),在这个过程中计算(x,y)即可

原文地址:https://www.cnblogs.com/luoshuitianyi/p/10333713.html