START:

2021-08-07

09:39:32

相关题目链接:

https://www.luogu.com.cn/problem/P1082

https://www.acwing.com/problem/content/879/

 

介绍:

为了介绍扩展欧几里得,我们先引入一个定理:

贝祖定理:

d=(a,b)代表最大公因数,则设a,b是不全为零的整数,则存在整数x,y,使得ax+by=d

(因为d是a和b的最大公因数,所以ax+by=dk,也就是说ax+by一定是d的倍数,所以存在x,y使得ax+by=d)

贝祖定理其中应用之一:如果ax+by=1有解,那么gcd(a,b)=1

 

再看一下欧几里得算法

求a和b的最大公约数:

int gcd(int a,int b)
{
  return b?gcd(b,a%b):a;  
}

  

但是对于ax+by=d,我们还得知道式子成立的时候x,y的值是多少,扩展欧几里得算法就是解决这个问题的。

扩展欧几里得算法是递归算法,我们算exgcd(a,b,x,y),就可以递归到exgcd(b,a%b,x,y)的状态,然后更新x,y

我们先写出最后状态的结果,就是exgcd(a,b,x,y)中b==0的时候,我们可以return a;

int exgcd(int a,int b,int &x,int &y){
    if(!b){
      x=1,y=0;
      return a; 
   }
}    

在这里我们写的扩张欧几里得函数,传入的参数有四个,a,b,x,y,其中x,y要使用引用,时刻改变x,y的值,当b==0的时候,我们ax+by=gcd(a,b)====>ax=a,所以x=1,y=0 是其中一个解,所以x=1,y=0。

在b!=0的时候,我们每次都可以递归exgcd(int a,int b,int &x,int &y)

比如exgcd(a,b,x,y),递归到exgcd(b,a%b,x,y)

我们展开其中实现的过程:

exgcd(a,b,x,y)====>exgcd(b,a%b,x,y)

exgcd(a,b,x,y):   ax+by=gcd(a,b)=d

exgcd(b,a%b,x1,y1):  bx1+(a%b)y1=gcd(b,a%b)=d===>因为a%b=a-(a/b)*b

所以上式等于    ay1+b(x1-[a/b]*y1)=d

我们对比一下前后两个状态的x,y

x=y1

y=x1-(a/b)*y1

所以前后两个状态的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,x,y);
   int tmp=y;
   y=x-a/b*y;
   x=tmp;
   return d;
}

END:

2021-08-07

10:29:47

 

posted on 2021-08-07 10:30  Dragon昴  阅读(86)  评论(2编辑  收藏  举报