欧几里得理解

欧几里得算法(辗转相除法)用来算多个数的最大公约数,(由于数学中最大公约数没有负数的概念,所以最大公约数不包括负数)
内容:gcd(a,b)=gcd(b,a%b)
证明:设a=x*b+r,设d为a,b的最大公约数,d|a,d|b,可得d|r,那么a%b=r,也就是gcd(a,b)=gcd(b,a%b)。

具体代码:

int gcd(int a,int b){
     

    if(!b)return a ;

    return gcd(b,a%b);
}

重点是扩展欧几里得和贝祖公式。

贝祖公式告诉我们:ax+by=gcd(a,b),【x,y为一组正整数】。

那么当我们要求am+bn=q时,如果q%gcd(a,b)!=0【q%gcd(a,n)!=0,q%gcd(m,b)!=0,q%gcd(m,n)!=0,其实都要满足,但是一般题目不会给你那么多已知量】,那么此方程无解。反之有无数组解【二元一次方程,要么无解,要么有无数组解】。

我们来一遍推导:

首先呢,gcd(a,b)=gcd(b,a%b)。 gcd(a,b)=ax1+by1,
那么很容易推导出gcd(b,a%b)=bx2+(a-a/bb)y2【此处为整除】,
按照a和b整理一下得到,a
x1=ay2,by1=b*(x2-a/by2)。
所以,x1=y2,y1=x2-a/b
y2。我们可以通过递归过程和引用将结果返回。

int extgcd(int a,int b,int &x,int &y){
     

    if(!b){
     

        x=1;y=0;

        return a;

    }

关于扩展欧几里得,还有个比较重要的东西,我们可以通过这个简单的得到一组x,y使得ax+by=gcd(a,b)或者是ax+by=c【可以判断有无解或者得到一组解】

但是刚刚也说了,二元一次方程如果有解是无数组的,那么如何通过这一组特解得到他们的通解呢。

设特解为x0,y0,通解为x0+m,y0+n。

ax0+by0=gcd(a,b)。

也就是说我们需要求出am+bn=0。ab/gcd(a,b)=ba/gcd(a,b),所以我们可以令m=b/gcd(a,b)*t,n=-a/gcd(a,b)*t。于是通解可以表示为x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t。在计算机中,负数mod正数,如果负数可以整除这个正数,返回0,否则就反悔满足同余的情况下的最大负数。所以说如果要求最小的非负x,

如果x>=0,那么直接x%(b/gcd(a,b))。

如果x<0,那么应该用x%(b/gcd(a,b)),得到满足同余的最大负数后,再加上b/gcd(a,b)得到最小正数解。也就是x%(b/gcd(a,b))+(b/gcd(a,b))

你可能感兴趣的:(算法)