• 浅谈 exgcd


    众所周知欧几里得算法是:

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

    也叫辗转相除法。

    拓展欧几里得算法(exgcd),可以用来找到形如 (ax+by=gcd(a,b)) 的方程的一组特解

    由裴蜀定理知,原方程一定有解。

    我们利用辗转相除法(普通欧几里得算法)。

    我们设 (d=gcd(a,b))

    我们可以知道,我们辗转相除法的边界是 (a=d,b=0),此时我们可以知道 (a) 就是最大公约数,我们还可以知道,在这时一定有一解为 (x=1,y=0),即 (1 imes a+0 imes b=d)

    我们知道 (gcd(a,b)=gcd(b,amod b)),如果我们可以推导出每一次的解 (x)(y),与相除后的解 (x')(y') 的关系;我们就可以算出其中的一个解了,((x)(y) 相当于是 (a) 和 $b (的解,)x'$ 和 (y')(a) 变成了 (b)(b) 变成了 (amod b) 时的解(辗转相除))。

    轻易得知:

    (egin{cases} ax+by=d\ bx'+(amod b)y'=d end{cases})

    则:

    [egin{aligned} bx'+left(a-bleftlfloordfrac{a}{b} ight floor ight)y'&=d\ bx'+ay'-bleftlfloordfrac{a}{b} ight floor y'&=d\ ay'+b(x'-leftlfloordfrac{a}{b} ight floor y')&=d\ ext{解得:}&egin{cases} x=y'\y=x'-leftlfloordfrac{a}{b} ight floor y' end{cases} end{aligned} ]

    然后我们知道 (x)(x')(y)(y'), 的关系后就可以求解了:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    void exgcd(int a,int b,int& x,int& y) //x.y也可以用pair返回,这里用了引用
    {
    	if (!b){x=1;y=0;return ;}     //边界
    	gcd(b,a%b);                   //辗转相除
    	int tmp=y;y=x-(a/b)*y;x=tmp;  //套公式
    }
    int main()
    {
    	int a,b,x,y;
    	scanf("%d %d",&a,&b);
    	exgcd(a,b,x,y);
    	printf("%d %d",x,y);
    	return 0;
    }
    
  • 相关阅读:
    Linux文件与文件系统的压缩
    Linux命令与文件查找
    js兼容pc和移动端的简单拖拽效果
    图片懒加载插件
    css小特效
    创建对象和方法
    距离2021年春节还剩。。。
    固定尺寸的图片焦点图案例
    数据库操作
    简单sql操作
  • 原文地址:https://www.cnblogs.com/CDOI-24374/p/12853932.html
Copyright © 2020-2023  润新知