拓展欧几里得算法

定义

对于不定方程 \(ax+by=c\) , \(d=gcd(a,b)\) 的求解中,人们发现当仅 \(d|c\),即 \(gcd(a,b)\)\(c\) 的因子时可得一组整数解 \((x,y)\).为求出使得 \(ax+by=d\) 的解,通常采用拓展欧几里得算法.

狭义的欧几里得算法即求 \(\text{gcd(a,b)}\) ,而广义的欧几里得算法希望进一步求出使得 \(ax+by=d=\text{gcd(a,b})\)\((x,y)\).

拓展欧几里得算法

\[\begin{cases} ax+by=d=gcd(a,b)\\ bx_1+(a\mod b)y_1=gcd(b,a\mod b)\\ gcd(a,b)=gcd(b,a\mod b)\\ a\mod b=a-kb \end{cases}\]

则整理:

\[ax+by=bx_1+(a-kb)y_1=ay_1+b(x_1-ky_1) \]

\[\Rightarrow \begin{cases} x=y1\\ y=x1-ky_1 \end{cases}\]

  1. \(b=0\) 时,显然 \(gcd(a,b)=a\),此时 \(x=1,y=0\)
  2. \(b\neq 0\) 时,则向下递归得 \(\text{Exgcd(b,a-kb)}\) 的解 \((x_1,y_1)\) ,并使 \((x,y)\leftarrow(y_1,x_1-ky_1)\)

其他(待补)

OI-Wiki

  • 迭代法
  • 矩阵法

代码

欧几里得

int gcd(int a,int b){
	if(a<b)swap(a,b);
	return b==0?a:gcd(b,a%b);
}

拓展欧几里得

int gcd(int a, int b, int& x, int& y) {
  x = 1, y = 0;
  int x1 = 0, y1 = 1, a1 = a, b1 = b;
  while (b1) {
    int q = a1 / b1;
    tie(x, x1) = make_tuple(x1, x - q * x1);
    tie(y, y1) = make_tuple(y1, y - q * y1);
    tie(a1, b1) = make_tuple(b1, a1 - q * b1);
  }
  return a1;
}

迭代

int gcd(int a, int b, int& x, int& y) {
  x = 1, y = 0;
  int x1 = 0, y1 = 1, a1 = a, b1 = b;
  while (b1) {
    int q = a1 / b1;
    tie(x, x1) = make_tuple(x1, x - q * x1);
    tie(y, y1) = make_tuple(y1, y - q * y1);
    tie(a1, b1) = make_tuple(b1, a1 - q * b1);
  }
  return a1;
}

矩阵

int exgcd(int a, int b, int &x, int &y) {
  int x1 = 1, x2 = 0, x3 = 0, x4 = 1;
  while (b != 0) {
    int c = a / b;
    std::tie(x1, x2, x3, x4, a, b) =
        std::make_tuple(x3, x4, x1 - x3 * c, x2 - x4 * c, b, a - b * c);
  }
  x = x1, y = x2;
  return a;
}
posted @ 2025-08-20 20:54  badn  阅读(3)  评论(0)    收藏  举报