欧几里德算法

辗转相除法:

其计算原理依赖于下面的定理:
定理:gcd(a,b) = gcd(b,a mod b) (a>b 且a mod b 不为0)//其实就是去掉因子b,这样就可以求出同样的最大公约数!
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个 公约数,则有
d|a,d|b,而r = a - kb,因此d|r
因此d也是(b,a mod b)的 公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证
或:证明:
第一步:令c=gcd(a,b),则设a=mc,b=nc
第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c
第三步:根据第二步结果可知c也是r的因数
第四步:可以断定m-kn与n互素【否则,可设m-kn=xd,n=yd,(d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数≥cd,而非c,与前面结论矛盾】
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r),得证
以上两种方法实质一样的。

利用欧几里德算法计算公约数:

#include<stdio.h>
intgcb(intmax,intmin)//求最大公约数
{
inttemp;
while(min!=0)
{
temp=max%min;
max=min;
min=temp;
}
returnmax;
}
intmain()
{
inta,b,temp;
scanf("%d %d",&a,&b);
printf("%d",gcb(a,b));
return0;
}


利用递归的方法求最大公约数:


#include<stdio.h>
int gcb(int a,int b)//假设a比b大
{
    int temp;
    temp=a%b;
    a=b;
    b=temp;
    if(b!=0)
        return gcb(a,b);
    else
        return a;
}
int main()
{
    int a,b;
    scanf("%d %d",&a,&b);
    printf("%d",gcb(a,b));
    return 0;
}
扩展欧几里德算法
基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。
证明:设 a>b。
  1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
  2,ab!=0 时
  设 ax1+by1=gcd(a,b);
  bx2+(a mod b)y2=gcd(b,a mod b);
  根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod b);
  则:ax1+by1=bx2+(a mod b)y2;
  即:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;
  根据恒等定理得:x1=y2; y1=x2-(a/b)*y2;
     这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
   上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。
代码如下:


本文出自 “我的算法笔记” 博客,谢绝转载!

你可能感兴趣的:(c,欧几里德,公约数)