扩展欧几里得算法

一、简单介绍

定理:若a和b为正整数,则存在x和y是的gcd(a,b)=ax+by;
换句话说gcd(a,b)可以表示为a、b的整数线性组合。
eg:

	gcd(6,14) = (-2)*6+1*14 = 2

已知整数a、b,扩展欧几里得算法可以在求解gcd的同时确定其系数。
首先,我们先模拟下欧几里得求解不定方程的过程
方程:

	252*x+198*y=18 // 18是gcd(252, 198)

以下g代表gcd(252, 198)
(1) 252=1*198 + 54
(2) 198=3*54+36
(3) 54=1*36+18
(4) 36=2*18
(3)式表示18可以表示为54和36的线性组合,即18=54-1*36
(2)式表示36=198-3*54,结合上面得18=54-1*(54-1*36)=54-1*(198-3*54)=4*54-1*198
(1)式表示54=252-1*198,结合上面得18=4*(252-1*198)-1*198=4*252-5*198
至此问题得到解决x=4,y=-5

二、递归推导

1、找到递归的出口

可以轻易得出算法的停止状态是:a=gcd,b=0,此时x=1, y=0

2、递归关系
一般情况下

a*x1+b*y1=gcd(a,b)
b*x2+(a%b)y2=gcd(b, a%b)

根据欧几里得我们知道

gcd(a,b)=gcd(b,a%b)
即
a*x1+b*y1=b*x2+(a%b)y2
而
a%b=a-[a/b]*b
所以
a*x1+b*y1=b*x2+(a-[a/b]*b)*y2
展开得到合并(关于a,b的方程)
a*x1+b*y1=a*y2+(x2-[a/b]*y2)*b
根据恒等定理得
x1=y2
y1=x2-[a/b]*y2

三、java实现

由上面我们翻译成java代码可得到

    /**
     * 扩展欧几里得算法:递归计算xa+yb=gcd(a,b)
     * @param a
     * @param b
     * @param r x=r[0], y=r[1]
     * @return gcd(a,b)
     */
    public static int extendGcd(int a, int b, int[] r) {
        if (b == 0) {
            r[0] = 1; r[1] = 0;
            return a;
        } else {
            int gcd = extendGcd(b, a%b, r);
            int t = r[0];
            r[0] = r[1];
            r[1] = t-(a/b)*r[1];
            return gcd;
        }
    }

四、通解

以上计算已经求出的是不定方程的一组解,x和y肯定一个为正一个为负。那么如何得出一组x必为正的解呢,这个也很好得到,假设上面求出的通解是x0,y0,那么就可以x0,y0来表示整个方程的通解:

	x=x0+(b/gcd)*t
	y=y0-(a/gcd)*t

验证

	a*x+b*y	=(a*x0+a*b/gcd*t)+(b*y0-b*a/gcd*t)
			=a*x0+b*y0=gcd

因为b/gcd与a/gcd互质,所以以上能表示所有通解
举例:
取a=17,b=3120,通过计算得到x0=-367,y0=2,gcd=1,

	x=-367+3120*t
	y=2-17*t

要使得x>0,t取1

	x=-367+3120*1=2753
	y=2-17*1=-15

代码链接

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值