LG的数学计划----EXGCD

拖延了好久了, 多重要的一章, 马上写, 不能再拖了, 写完了去写作业

  • 首先介绍一下欧几里得算法

gcd(a,b)=gcd(b,amodb)

内容很简单, 关于此定理的算法也称辗转相乘法, 且gcd(a, b) = gcd(b, a);
证明非常简单:

我们令 a = kb+u; 则 u = a % b = a-kb;
设gcd(a, b) = g; 则g|a, g|b, 
∵u = a-kb
∴g|u
  • 接下来说说exgcd

    这个东西用于求整数对(x, y)满足

    ax+by=gcd(a,b);

1.对于b=0, 显然解为(1, 0)
2.对于a > b > 0

我们可以构造两个式子,设原式的解之一为x1, y1.
则ax1 + by1 = gcd(a, b);
满足下一式的解为x2, y2
bx2 + a%by2 = gcd(b, a%b);
我们知道欧几里得定理那么—->
ax1+by1 = bx2 +(a-a/b*b)y2;
————= ay2+bx2-a/b*by2
————= ay2+b* (x2-a/b*y2)

一个叫恒等定理的东西
我们可以直接对两边系数划等号
即x1 = y2, y1 = x2-a/b*y2
那么我们用一个递归就可以解决了,
给出代码写作业去了

void exgcd(ll a, ll b, ll &x, ll &y) {
    if(!b) {
        x = 1; y = 0;
    }
    else {
        exgcd(b, a%b, y, x);
        y -= a/b*x;
    }
}

二次编辑

对于exgcd这里还有一些补充的地方,
当我们已求出一对通解时其实并不够题目往往会给我们一些其他的问题,
如求出x的最小非负整数解, 对于这样的处理

/*
我们假设我们已经求出一组通解x0, y0
满足 ax0+by0 = gcd (a, b);

那么假设我们需要求出其他解x1, y1;
ax1+by1 = gcd(a, b);

两式相减我们发现a(x1-x0) + b(y1-y0) = 0;
我们发现当x1-x0 == a * b/gcd(a, b), y1-y0 == b * a/gcd(a, b);
刚好可以满足等式, 那么我们就可以用这样的办法不停构造其他无数组解
而且你可以发现没有比这使两组解之差更小的办法, 
那么求解时只要加这么一句话设x0是exgcd后答案
int d = b/gcd(a, b);
这就是最小非负整数了(x0%d+d)%d;
*/
原文地址:https://www.cnblogs.com/pbvrvnq/p/8530159.html