1. 程式人生 > 其它 >springCloud-微服務相互呼叫-RestTemplate

springCloud-微服務相互呼叫-RestTemplate

定義

擴充套件歐幾里得演算法是歐幾里得演算法(又叫輾轉相除法)的擴充套件。已知整數\(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)