数论拓展gcd基础

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/w_udixixi/article/details/100609293

exgcd求解一般线性方程组ax+by=c

算法复杂度是 O ( l o g ( a + b ) ) O(log(a+b))
其实等同于求解 a x + b y = M g c d ( a , b ) ax+by=Mgcd(a,b) 这个方程,首先看第一种情况

1.首先考虑ax+by=m,且m%gcd(x,y)!=0

这种情况下肯定无解,不作证明,证明比较简单

2.然后考虑 a x + b y = g c d ( a , b ) ax+by=gcd(a,b)

由于 g c d ( x , y ) = g c d ( y , x % y ) gcd(x,y)=gcd(y,x\%y) ,直到y=0此时返回x的值就等于 g c d ( x , y ) gcd(x,y)
(这是gcd最核心的难点理解)

a x 1 + b y 1 = g c d ( a , b ) = g c d ( b , a % b ) ax_1+by_1=gcd(a,b)=gcd(b,a\%b)
= b x 2 + y 2 ( a % b ) = b x 2 + y 2 ( a a / b =b*x_2+y_2*(a\%b)=b*x_2+y_2*(a-\lfloor a/b \rfloor *b)

我们设a,b是未知量
则可以知道
x 1 = y 2 ; x_1=y_2;
y 1 = x 2 a / b y 2 y_1=x_2-\lfloor a/b \rfloor*y_2

(这个叫递归算法核心?

3.考虑 a x + b y = M g c d ( a , b ) ax+by=M*gcd(a,b) (M是非零整数)

其实就是先求解 ( a / M ) x + ( b / M ) y = g c d ( x , y ) (a/M)x+(b/M)y=gcd(x,y) 的情况,得到的 x 0 = M x_0*=M
g c d ( a , b ) = g gcd(a,b)=g
解出的x解系还原回去

{ x = c g x 0 + k b g y = c g y 0 k a g 最终解系 \begin{cases} x = {c\over g}x_0+k{b\over g}\\ y= {c\over g}y_0-k{a\over g} \end{cases}

如果要求x的最小整数解的话,就要加一部对x的操作,具体见代码
如果要求对应的y的话,直接代回原方程即可

ll exgcd(ll a,ll b,ll &x,ll &y)
//&必须写的原因是并不是x,y是作为一个地址在进行递归,所以需要取地址符
{
    if (b==0)
    {
        x=1;
        y=0;
        return a;
    }
    else
    {
        ll gcd=exgcd(b,a%b,y,x);
        y-=x*(a/b);
        return gcd;
    }
}
int main()
{
    a=;b=;c=;
    g=exgcd(a,b,x,y);//返回的是a,b的gcd
    if (c%g!=0) {cout<<"Impossible"<<endl;return 0;}
    //如果c不是gcd(a,b)的倍数的话,就无法求解,不作证明
    ll M=c/g;
    x*=M;
    ll t=b/g;
    if (b<0)b=-b;
    x=(x%t+t)%t;//根据解系求最小整数解,注意此时的b一定要是非负数
    WW(x);
    //如果要求y的话就根据原方程进行转化可得到

猜你喜欢

转载自blog.csdn.net/w_udixixi/article/details/100609293
今日推荐