< a href=" ">< img border="0" src="https://cc.amazingcounters.com/counter.php?i=3197494&c=9592795" alt="AmazingCounters.com">

欧几里得算法

欧几里得算法:

辗转相除计算两个数的最大公约数。求gcd(a,b)。

代码:

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

 

扩展欧几里得算法:

存在整数对(x,y)使得ax + by = gcd(a,b)

证明:

设a > b

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

当b!= 0 时,设

a * x1 + b * y1 == gcd(a,b)

b * x2 + a%b * y2 == gcd(b,a%b)

因为 gcd(a,b)==gcd(b,a%b),所以a * x1 + b * y1 == b * x2 + a%b * y2

a * x1 + b * y1 == b* x2 +(a-(a/b)*b)*y2

则 x1 = y2,y1 = x2 - (a/b) * y2;

代码:

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

应用:

1.求解不定方程:

c%gcd(a,b)=0,则存在整数对(x,y)使得ax+by=c

 

通过上面的方法可得到一组特解x0y0使得ax+by=gcd(a,b),那么如何在无穷多个解中求出xy最小正整数解。

证明:

首先 ax0+akb/gcd(a,b)+by0akb/gcd(a,b)=gcd(a,b) 
即 a(x0+kb/gcd(a,b))+b(y0ka/gcd(a,b))=gcd(a,b) 
通解为x=x0+kb/gcd(a,b)y=y0ka/gcd(a,b),其中k=...2,1,0,1,2... 
在所有解中最小的正整数为(x0+b/gcd(a,b))%(b/gcd(a,b)), 
所以对于方程ax+by=c,最小正整数解(以x为例)为(x0c/gcd(a,b)+b/gcd(a,b))%(b/gcd(a,b)) 
注意:若b为负数,需将b转换为正数。

代码:

int ex_gcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int d = exgcd(b,a%b,x,y);
    int t = x;
    x = y;
    y = t - a/b * y;
    return d;
}
int cal(int a,int b,int c)
{
    int x,y;
    int g = ex_gcd(a,b,x,y);
    if(c%g!=0)
        return -1;
    x *= c/g; ///x0 * c/gcd(a,b);
    
    b /= g;///b/gcd(a,b);
    if(b<0)
        b = -b;
    int ans = x%b;
    if(ans<=0) ans +=b;
    return ans;
}

 

2.同余定理:

根据上面的内容,我们可以得到:

  • axb(modn),转化为ax+ny=b,当 b%gcd(a,n)=0时,方程有 gcd(a,n) 个解。
  • ax1(modn),如果gcd(a,n)=1,则方程有唯一解。

 

posted @ 2017-07-24 14:26 琄甃 阅读(...) 评论(...) 编辑 收藏
< a href=" ">< img border="0" src="https://cc.amazingcounters.com/counter.php?i=3197494&c=9592795" alt="AmazingCounters.com">