基础数论-扩展欧几里得算法

Dear 丶 2022-05-24 11:16 305阅读 0赞

首先我们先了解欧几里得算法

求俩个数a,b的最大公约数gcd(a,b)

根据贝祖定理得,gcd(a,b)=gcd(b,a-b),(a>b) 直到b为0时,a就是答案,但是这样时间复杂度有点高,因为a-b并不能保证一定大于b,所以我们又会做一次同样操作,即gcd(a,b)=gcd(b,a mod b)。

时间复杂度log N

代码如下:

  1. int gcd(int a,int b)
  2. {
  3. return b==0?a:gcd(b,a%b);
  4. }

扩展欧几里得算法:

对于这样的方程ax+by=gcd(a,b) 求出满足方程的x,y

通过刚刚的欧几里得算法,

当b==0时 ,ax+0*y=gcd(a,0) x=1 y=0

当b>0时,那么根据欧几里得算法 gcd(a,b)=gcd(b,a mod b)

b*x`+(a mod b) y` =gcd(b,a mod b) =gcd(a,b)

ax + by =gcd(a,b)

我们把第一个式子按照第二个式子化简

b*x`+(a-a/b*b)*y` =gcd(a,b)

ay`+b(x`-a/b*y`) =gcd (a,b)

即x=y` 和 y=(x`-a/b*y`)

我们一直递归到b=0,然后把x=1 y=0代入。

时间复杂度log N

代码如下:

  1. int extend_gcd(int a,int b,int &x,int &y)
  2. if (b==0) {
  3. x=1;y=0;
  4. return a;//返回的结果是最大公约数
  5. } else {
  6. int d=exgcd(b,a%b,y,x);//x 和y 的位置换了注意
  7. y-=(a/b)*x;
  8. return d;
  9. }
  10. }

单变元模线形方程

对于这样的方程 ax=b mod n 我们可以转化为 ax +ny =b 我们令d=gcd(a,n)

当b整除d时有解,d个,否则无解。

假设我们已经求出 ax + ny = gcd(a,n) =d

那么 ax +ny = b 的解为X=x* b/d;

令X1 Y1 X2 Y2为方程ax + ny =b 的俩组解

aX1 + bY1 =b

aX2 + bY2 =b

即a(X1-X2)=b(Y2-Y1) 我们俩边同时除以d

a/d *(X1-X2)=n/d * (Y2-Y1) 因为d为gcd(a,n)那么gcd(a/d ,n/d)=1 即互质

那么X1-X2=k *(n/d) 和 Y2-Y1=k` (a/d) 俩个k不一样咯注意。

即X1=X2+k*(n/d) Y1=Y2-k`*(a/d)

通解已经推出了 不难发现 ,当k为d时,在模n下 X1=X2+n 与前面重复,所以k的取值为[0,d-1]

最小正整数解 X0=(X1 %(n/d) +(n/d) )% (n/d)

  1. vector<int> line_mod_equation(a,b,n)
  2. {
  3. int x,y;
  4. int d=extend_gcd(a,b,x,y);
  5. vector<int > ans;
  6. ans.clear();
  7. if (b%d==0) {
  8. x=(x%n+n)%n;
  9. ans.push_back(x*(b/d)%(n/d));
  10. for (int i=d;i<d;i++) {
  11. ans.push_back((ans[0]+i*(n/d))%n);
  12. }
  13. }
  14. return ans;
  15. }

发表评论

表情:
评论列表 (有 0 条评论,305人围观)

还没有评论,来说两句吧...

相关阅读

    相关 扩展算法

    poj 1061题目,青蛙的约会。一开始想暴力求解的。但是之前提交过,tle... 今天过来查一下,说是扩展欧几里得算法。我了个去。这么复杂的名字,得是有多深奥。 查了才知

    相关 扩展算法

    问题描述: 求解二元一次方程ax+by=c。 问题分析: 上述的二元一次方程可以用同余方程来进行描述:ax≡cmod(b) 两个问题可以进行转换,但是都可以用扩展的欧几