[数学]gcd&exgcd

gcd & exgcd


gcd

我们规定:

\[\begin{equation}gcd(a,b)=a,b的最小公倍数\nonumber\end{equation} \]

显然我们有:

\[\begin{align}a&=k_1\times gcd(a,b)\nonumber\\b&=k_2\times gcd(a,b) \nonumber\\a\%b&=a-\lfloor\frac{a}{b}\rfloor\times b\nonumber\\&=k_1\times gcd(a,b)-\lfloor\frac{a}{b}\rfloor\times k_2\times gcd(a,b)\nonumber\\&=gcd(a,b)\times (k_1-k_2\times\lfloor\frac{a}{b}\rfloor)\nonumber\end{align} \]

显然\(k_1,k_2,\lfloor\frac{a}{b}\rfloor\)均为整数,且\(gcd(k_1,k_2\times \lfloor\frac{a}{b}\rfloor)=1\)

\(a\%b\)也是\(gcd(a,b)\)的倍数

那么我们就有:

\[\begin{equation} gcd(a,b)=gcd(b,a\%b)\quad当且仅当a\%b=0时,gcd(a,b)=a\nonumber\end{equation} \]

下面是代码实现:

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

exgcd

我们要求解形如下面的方程的一组整数解:

\[\begin{align}ax+by=d\nonumber\end{align} \]

首先,这样的方程并不是一定有解的,我们有裴蜀定理:

\[当且仅当gcd(a,b)|d时,ax+by=d有整数解 \]

所以如果方程有解,我们就可以操作一下它:

\[\begin{align}ax+by&=k\times gcd(a,b)\nonumber\\a(x_1\times k)+b(y_1\times k)&=k\times gcd(a,b)\nonumber\\ax_1+by_1&=gcd(a,b)\nonumber\end{align} \]

于是我们就把方程简化到上面的形式,它的一组解是\((x_1,y_1)\)

那么原方程的一组解就是\((x_1\times k,y_1\times k)\),其中\(k=\frac{d}{gcd(a,b)}\)

接下来我们考虑怎么解简化后的方程:

\[\begin{align}ax+by&=gcd(a,b)\nonumber\\ax+by&=gcd(b,a\%b)\nonumber\\bx'+(a\%b)y' &=gcd(b,a\%b)\nonumber\\bx'+(a-\lfloor\frac{a}{b}\rfloor\times b)y'&=ax+by\nonumber\\bx'+ay'-b\times\lfloor\frac{a}{b}\rfloor\times y'&=ax+by\nonumber\\ay'+b(x'-\lfloor\frac{a}{b}\rfloor\times y')&=ax+by\nonumber\\ay'+b(x'-\lfloor\frac{a}{b}\rfloor\times y')&=gcd(b,a\%b)\nonumber\end{align} \]

我们可以根据最后一行式子递归下去求解

直到\(a\%b=0\)时,\(gcd(a,b)=0\),此时的一组解为\(\left\{\begin{align}x=1\nonumber\\y=0\nonumber\end{align}\right.\)

这是最后一层的答案,我们考虑怎么通过这个得到上一层的答案

观察倒数第二行的式子,我们可以得到\(\left\{\begin{align}x&=y'\nonumber\\y&=x'-\lfloor\frac{a}{b}\rfloor\times y'\nonumber\end{align}\right.\)

通过这个我们就可以一层一层向回推,得到最后的解了

代码:

#include<bits\stdc++.h>

using namespace std;

int gcd(int a,int b){
    return b?a:gcd(b,a%b);
}

void exgcd(int a,int b,int &d,int &x,int &y){
    if(b==0){
        d=a;
        x=1;
        y=0;
    }else{
        exgcd(b,a%b,d,y,x);
        y=y-a\b*x;
    }
}

int main(){
    int a,b,d;
    scanf("%d%d%d",&a,&b,&d);
    int tmp=gcd(a,b);
    if(d%tmp)
        printf("no solution!\n");
    else{
        int x,y;
        exgcd(a,b,tmp,x,y);
        x=x*d/tmp;
        y=y*d/tmp;
        printf("%d %d\n",x,y);
    }
}
posted @ 2020-09-11 13:55  Remilia_Saikou  阅读(208)  评论(4编辑  收藏  举报