裴属定理与拓展欧几里得算法

目录

目录地址

上一篇

下一篇


裴属定理

裴蜀定理(或贝祖定理)得名于法国数学家艾蒂安·裴蜀,其形式上可以表现为:

对于 \(\forall a,b\in Z_+\) ,设 \(d=gcd(a,b)\)

则一定存在 \(x,y\in Z_+\) 使得: \(ax+by=d\)

证明:

设存在 \(x,y\in Z_+\) 使得 \(ax+by=d\) 成立

\(ax+by=gcd(a,b)=gcd(b,a\mod b)=gcd(b,a-(a/b)\cdot b)\) 得到

\(ax+by=bx'+[a-(a/b)\cdot b]y'=ay'-b(x'-(a/b)\cdot y')\)

因此得到:若 \(b\)\(a\mod b\) 存在解 \(bx'+(a\mod b)y'=gcd(b,a\mod b)=d\)

则存在 \(x,y\)

又因为将该过程视为递归,则递归的边界为 \(a''=gcd(a,b),b''=0\) 显然有解 \(x''=1,y''=0\)

因此存在 \(x,y\)

裴属定理的推论

由于存在 \(ax+by=gcd(a,b)\)

故对 \(\forall k\in Z_+\) 都存在 \(X,Y\in Z_+\) 使得 \(aX+bY=k\cdot gcd(a,b)\)

证明:

\(x,y\in Z_+\) 使得 \(ax+by=gcd(a,b)\)

\(X=kx,Y=ky\) 得到 \(aX+bY=akx+bky=k(ax+by)=k\cdot gcd(a,b)\)

裴属定理的推广形式

存在 \(x_{1\dots n}\in Z_+\) 使得 \(\displaystyle \sum_{i=1}^na_ix_i=\text{gcd}_{i=1}^n\ a_i\)

其中 \(\text{gcd}_{i=1}^n\ a_i\) 表示 \(a_{1\dots n}\) 的最大公因数

证明: \(n=2\) 我们已经证明

\(n=k\) 时成立, \(d=\text{gcd}_{i=1}^k\ a_i\)

则存在 \(x'_{1\dots k}\) 使得 \(\displaystyle \sum_{i=1}^ka_ix'_i=d\)

由于存在 \(c,x_{k+1}\in Z_+\) 使得 \(cd+a_{k+1}x_{k+1}=gcd(d,a_{k+1})\)

\(x_i=cx'_i,i\in[1,k]\bigcap Z\) 得到 \(\displaystyle \sum_{i=1}^{k+1} a_ix_i=gcd(d,a_{k+1})\)

\(c_i\)\(a_{1\dots k}\)\(i\) 个因数的次数的最小值, \(d_i\)\(a_{k+1}\) 的第 \(i\) 个因数的次数 ,则 \(\displaystyle d=\prod_{i=1}^mp_i^{c_i}\)

因此 \(\displaystyle gcd(d,a_{k+1})=\prod_{i=1}^mp_i^{min(c_i,d_i)}=\text{gcd}_{i=1}^{k+1}\ a_i\)

故原命题得证

同时,我们也得到很重要的性质:

\(\text{gcd}_{i=1}^n\ a_i=gcd(\text{gcd}_{i=1}^{n-1}\ a_i,a_n)\)


拓展欧几里得算法

由上面的方法,我们发现,实际上 \(x,y\) 是事实可求的值

由递归过程:

\(\begin{cases} a=b \\\ \\ b=a\mod b \\\ \\ x=y' \\\ \\ y=x'-(a/b)\cdot y' \end{cases}\)

递归边界为:

\(\begin{cases} a \\\ \\ b=0 \\\ \\ x=1 \\\ \\ y=0 \end{cases}\)

因此写出代码:

int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    int g=exgcd(b,a%b,x,y);
    int tmp=x;
    x=y;
    y=tmp-a/b*x;
    return g;
}

或者有人会发现,实际上递归式中的 \(x,y\) 可以理解为:

\(x,y\) 交换,然后 \(y-=(a/b)\cdot x\)

因此非递归写为:

int exgcd(int a,int b,int &x,int &y){
    int m=b,tmp[10000]={0},cur=1;
    x=1,y=0;
    tmp[0]=a/b;
    while(b^=a^=b^=a%=b) tmp[cur++]=a/b;
    while(cur--) y^=x^=y^=x-=tmp[cur]*y;
    return a;
}
posted @ 2020-03-01 10:38  JustinRochester  阅读(369)  评论(0编辑  收藏  举报