扩展欧几里得

定义

扩展欧几里得算法是欧几里得算法(又叫辗转相除法)的扩展。已知整数\(a,b\),扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使他们满足等式:\(ax+by=gcd(a,b)\)


问题

已知\(a,b\),求满足\(ax+by=gcd(a,b)\)的整数 \(x\)\(y\)。其中 \(x\) 应当是满足条件的最小正整数,\(y\) 是辅助答案。

模板题 P1082 同余方程


由欧几里得算法知

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

如果现在存在\(x_2,y_2\)使得

\[bx_2 + (a \bmod b)y_2 = gcd(b, a \bmod b) \]

那么会有

\[ax + by = bx_2 + (a \bmod b)y_2 \]

\[\Downarrow \]

\[ax + by = bx_2 + (a-b×(a/b))y_2 \]

\[\Downarrow \]

\[ax + by = bx_2 + ay_2 - b × (a/b)y_2 \]

\[\Downarrow \]

\[ax + by = ay_2 + b(x_2-(a/b)y_2) \]

此时得到一组显然解

\[\begin{cases}x = y_2\\y = x_2-(a/b)y_2\end{cases} \]

容易想到:可以采取递归的方法,重复这个过程直至普通欧几里得算法递归基

\[b = 0 \]

此时易知使得\(ax_n+by_n=gcd(a,b)\)成立即

\[\begin{cases}x_n = 1\\y_n = 0\end{cases} \]

在回溯过程中可计算得到所求\(x,y\)


解的处理

此时已经求得了一组满足题意的\(x,y\)

但是\(x\)最小正整数的要求并未满足,此时\(x\)可能偏大或偏小(为负值)

已知\(ax + by = 1\),那么

\[ax + by + k×ba - k×ba = 1 \]

\[\Downarrow \]

\[a(x+kb) + (y-ka)b = 1 \]

可以看出 \(x\)\(b\)的倍数 为变化量变化时,总能满足题意

\(ax + by = 1\)\(\frac{1-ax}{b} = y\)

\(1-ax\)是b的倍数

那么要得到符合题意的\(x,y\) 必然要使\(1-ax\)的变化量为\(b\)的倍数

\(x\)变化量必然为b的倍数

那么相当于我们证明了

  • 在所求\(x\)基础上使\(x\)\(b\)的倍数为变化量变化,总能得到满足题意的最小正整数\(x\)

代码实现

#include <iostream>

using namespace std;

long long x , y;
void exgcd(long long a , long long b){
  //if(a < b) return exgcd(b , a);
  if(b == 0){
    x = 1 , y = 0;
    return;
  }
  exgcd(b , a % b);
  long long tmp = x;
  x = y , y = tmp - (a / b) * y;
}
int main(){
  long long a , b;
  cin >> a >> b;
  exgcd(a , b);
  while(x < 0) x += b;
  x %= b;
  cout << x << endl;
}

参考文章:

题解 P1082 【同余方程】
(作者:学委

Exgcd(作者:samzhang)

posted @ 2022-04-11 16:39  skyliyu  阅读(24)  评论(0编辑  收藏  举报