數論——擴展歐幾里得算法與線性同餘方程

1、擴展歐幾里得算法ios

裴蜀(Bézout)定理算法

對任何整數a、b和它們的最大公約數d=gcd(a,b),必定存在整數x,y,使ax+by=d成立。 
  下面證實裴蜀定理:

證實:spa

  在歐幾里得算法的最後一步,即b=0時,顯然有一對整數x = 1,y = 0,使得a*1+0*0=gcd(a,0)。code

  當b>0時,blog

  ∵ by + (a mod b) x = d,即 by + (a - a/b * b) x = d(注:a/b下取整)。遞歸

  ∴ 整理得 ax + b(y - a/b * x)=d。get

  令x' = x,y' = y,因而 ax' + by' = d。因此x'和y'就是知足條件的一組解。數學

  由歐幾里得算法遞歸過程及數學概括法,可知裴蜀定理成立。it

  證畢!io

  由上述證實過程可得整數x和y的計算方法,這種計算方法被稱爲擴展歐幾里得算法

代碼實現

  模板題連接:擴展歐幾里得算法

  代碼以下:

int exgcd(int a,int b,int &x,int &y) { if(!b) { x=1;y=0; return a; } int d=exgcd(b,a%b,y,x); y-=a/b*x; return d; }

ax+by=d的通解

x = x0 + k*(b/d)

y = y0 - k*(b/d)

其中k能夠是任意一個整數,x0,y0是ax+by=d的一組特殊解。

  下面證實上式的正確性:

  ax + by = a(x0 + k(b/d)) + b(y0 - k(a/d)) = ax0 +by0 + k(ab/d) - k(ab/d) =d。

  下面證實ax+by=d的通解均是上述形式:

證實:

  ax0 + by0 = d

  ax' + by' =d

  做差可得:a(x0 - x') + b(y0 - y') = 0

  等式兩邊同除以d得,a/d(x0 - x') + b/d(y0 - y') = 0

  移項得,a/d(x0 - x') = - b/d(y0 - y')

  由於d是a和b的最大公約數,因此(a/d)與(b/d)互質。

  又由於 (b/d) | a/b(x0 - x'),因此 (b/d) | (x0 - x')。

  因此x0 - x' = k * (b/d),即x' = x0 - k * (b/d)。

  因爲k能夠是任意的整數,因此上式等價於x' = x0 + k * (b/d)。

  證畢!

2、線性同餘方程

解法原理

給定整數a,b,m,求一個整數x知足axb(mod m),或者給出無解。

  a * x ≡ b(mod m),等價於 ax + my = b(b必定是gcd(a,m)的倍數)。

  下面給出證實:

證實:

  設ax mod m = b mod m = r

  mk1 + r =ax

  mk2 + r =b

  其中k1,k2都是整數,

  做差得:m(k1 - k2) = ax - b

  因此 ax = mk +b

  證畢!

  根據擴展歐幾里得算法,能夠獲得 ax' + my' = d(d = gcd(a,m))的一組解x'和y'。

  那麼在其等式兩邊同乘上(b/d)便可得:a((b/d)x') + m((b/d)y') = d * (b/d) = b。

  因而咱們便獲得了線性同餘方程的一組解即爲x = (b/d)x'和y = (b/d)y'。

  由於只要求x,因此只需返回x便可。

代碼實現

  模板題連接:線性同餘方程

  根據上述原理,咱們只須要用歐幾里得算法得出一組解以後,再將x乘上(b/d)便可。

  代碼以下:

#include <iostream> #include <algorithm> #include <cmath> #include <cstdio>
using namespace std; int exgcd(int a,int b,int &x,int &y) { if(!b) { x=1;y=0; return a; } int d=exgcd(b,a%b,y,x); y-=a/b*x; return d; } int main() { int n;scanf("%d",&n); for(int i=1;i<=n;i++) { int a,b,m;scanf("%d%d%d",&a,&b,&m); int x,y; int d=exgcd(a,m,x,y); if(b%d) { puts("impossible"); continue; } x=(long long)x * (b/d) % m; printf("%d\n",x); } return 0; }
相關文章
相關標籤/搜索