(扩展)欧几里得算法

欧几里得算法——求最大公约数:

使用辗转相除法。

// 欧几里得——递归
int gcd1(int a, int b)
{
    return b==0 ? a : gcd1(b, a%b);
}
// 欧几里得——非递归
int gcd2(int a, int b)
{
    int t;
    while(b!=0){
        t = a;
        a = b;
        b = t%b;
    }
    return a;
}

扩展欧几里得算法

扩展欧几里得算法不仅能确定两个正整数的最大公约数,如果这两个数互素,还能确定它们的逆元
gcd(a,b)=1 , 那么 a 有一个模 n 的乘法逆元: a1 。即 aa1=1modb
同时满足方程: ax+by=1 ,存在一组(x,y)解。

例子
用类似辗转相除法,求二元一次不定方程 47x+30y=1 的整数解。(递归)
47 = 30 * 1 + 17
30 = 17 * 1 + 13
17 = 13 * 1 + 4
13 = 4 * 3 + 1
然后把它们改写成“余数等于”的形式
17 = 47 * 1 + 30 * (-1) //式1
13 = 30 * 1 + 17 * (-1) //式2
4 = 17 * 1 + 13 * (-1) //式3
1 = 13 * 1 + 4 * (-3)
然后把它们“倒回去”
1 = 13 * 1 + 4 * (-3)
1 = 13 * 1 + [17 * 1 + 13 * (-1)] * (-3) //应用式3
1 = 17 * (-3) + 13 * 4
1 = 17 * (-3) + [30 * 1 + 17 * (-1)] * 4 //应用式2
1 = 30 * 4 + 17 * (-7)
1 = 30 * 4 + [47 * 1 + 30 * (-1)] * (-7) //应用式1
1 = 47 * (-7) + 30 * 11
得解x=-7, y=11。

// 扩展欧几里得(递归),若返回 gcd=1,则 a^-1 = x
int exEuclid1(int a, int b, int &x, int &y)
{
    if(b==0){        //上一个 b = 1, a % b = 0
        x = 1;  
        y = 0;
        return a;    // a 即上一个 b,此时 a = 1,则 gcd=1  
    }
    int g = exEuclid1(b, a%b, x, y); 
    int t = x;               
    x = y;          
    y = t - a/b * y;     
    return g;
}

当前式子:
ax+by=gcd
下次循环:
bx1+(a%b)y1=gcd
化简整理:
ay1+b(x1a/by1)=gcd

来自维基百科

// 扩展欧几里得(非递归),若返回 gcd=1,则 a^-1 = x(即y1)
int exEuclid2(int a, int b, int &x, int &y)
{
    int x1=1, x2=0, x3=a;  //47 1 0
    int y1=0, y2=1, y3=b;  //30 0 1
    int t1, t2, t3;
    int q;
    while (1){
        if (y3 == 0) {
            x = x1; y = x2; // y3 即上一个循环的余数,y3=0 说明无逆元 
            return x3;
        }
        else if (y3 == 1){  // y3=1 即上一个循环的余数为 1,有逆元 
            x = y1; 
            y = y2;
            return y3;
        }
        q = x3/y3;
        t1=x1-q*y1; t2=x2-q*y2; t3=x3-q*y3;
        x1=y1; x2=y2; x3=y3;
        y1=t1; y2=t2; y3=t3;
    }
}

参考资料:扩展欧几里得算法 - 维基百科

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值