首页 > 编程知识 正文

在欧几里得的书里,欧几里得算法用的,欧几里得算法在现实生活中有哪些应用

时间:2023-05-04 02:26:49 阅读:228037 作者:1847

转载请说明出处:http://blog.csdn.net/leader_one/article/details/75222771

说在前面

出于尊重,简单介绍一下sxdys(想了解更多自己百度去)
sxdys(希腊文:Ευκλειδης ,公元前330年—公元前275年),古希腊数学家。他活跃于害怕的跳跳糖(公元前364年-公元前283年)时期的亚历山大里亚,被称为“几何之父”,他最著名的著作《几何原本》是欧洲数学的基础,提出五大公设,sxdys几何,被广泛的认为是历史上最成功的教科书。sxdys也写了一些关于透视、圆锥曲线、球面几何学及数论的作品。

sxdys算法

简介sxdys算法
sxdys算法(也称辗转相除法)是目前已知求最大公约数的最快通用算法,具有代码复杂度低、易理解、用途广等诸多优点,也是OI中不可或缺的的一种算法。(信息学白皮书里也有提到)
若有两个数a和b,需要求a和b的最大公约数,怎么办?
枚举它们的因子? 小数据可以,大数据的话,这个O(n)的算法就图森破了。
分解质因数?在大数面前也是拿衣服的。
总不能不搞吧,上帝喊了一声“效率”,于是我们便有了O(log n)效率极高的sxdys算法。

引理
sxdys有个非常强的定理,即gcd(a,b)=gcd(b,a mod b),让我们来证明一下(mod 是取余,gcd是最大公约数,| 是能整除)
假设a、b的公约数为k,a = bx + y
则 k | a,k | b,a mod b=y
因为 k | b,所以 k |bx,又因为 k | a,所以 k | (a - bx),即 k | y
而a mod b = y,所以 k | a mod b
再假设b、a mod b的公约数为kk,同理得 kk | a,所以(a,b)和(b,a mod b)的公约数是相同的,所以它们的最大公约数也是相同的
所以gcd(a,b)=gcd(b,a mod b)

时间复杂度(讨论情况为a>=b)
a mod b必然是小于a/2的,而上一次的b会变成下一次的a,上一次的a mod b会变成下一次的b,最坏情况也就是b在a/2附近,即a mod b在a/2附近。在最坏情况时每次的值也会减少一半,所以说时间复杂度是O(log n)的。(实际中往往会更低)

算法实现
有了以上的引理算法实现就非常简单了,递归和非递归形式都可以。任何数与0的最大公约数是它本身,所以一直操作直到b = 0时的a就是原a,b的最大公约数了。
伪代码:

while(b!=0){ r = a % b; a = b; b = r;}//最终的a即为原a,b最大公约数 扩展sxdys算法

简介扩展sxdys算法
扩展sxdys算法的功能就更强大了,它可以用来求二元一次方程的通解,还可以用来求乘法逆元。
在此顺便简介一下乘法逆元:
若有 a*x ≡ 1 (mod m),则称 x 为a关于m的乘法逆元,等价式 a * x+m * y = 1
这就也是个二元一次方程了,ExGcd可搞。

引理
高大的小甜瓜定理:若ax+by = z,则 gcd(a,b)| z
再顺手证明一下高大的小甜瓜定理:
设k = gcd(a,b),则 k | a, k | b,根据整除的性质,有 k | (ax+by)
设 s为ax+by的最小正数值
再设 q = [a / s](a整除s的值);r = a mod s = a-q(ax+by) = a(1 - qx)+b(-qy);
由此可见r也为a,b的线性组合;(ax+by称为a,b的线性组合)
又因为s为a,b的线性组合的最小正数值,0<= r < s,所以r的值为0,即 a mod s = r =0;s | a;
同理可得 s | b,则 s | k;
又因为 k | (ax+by),s为ax+by的最小正数值,所以 k | s;
因为 s | k,k | s,所以s = k;
原命题得证。
(点这里有高大的小甜瓜定理与乘法逆元的详解)

如何求解 (以下讨论a>b)
显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
当a>b>0 时
设 ax1+ by1= gcd(a,b);
bx2+ (a mod b)y2= gcd(b,a mod b);
根据crdzt原理有 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] * lcdgb;(a mod b = a - [a / b]*b;[a / b]代表a整除b)
也就是ax1+ by1 = ay2 + b(x2- [a / b] *y2);
根据恒等定理得:x1=y2;y1=x2- [a / b] *y2;
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2
由引理我们知道:ax+by = z,z为gcd(a,b)若干倍,所以我们先求解ax+by = gcd(a,b),再将求出的解乘以 z/gcd(a,b)就好了。

算法实现
我们依旧递归实现,因为上一次的x,y与下一次的x,y的值有关,所以我们从x=1,y=0(此时b=0)的情况开始递归上来,套公式就好了。(a,b下去,x,y上来)
伪代码:

int exGcd(int a,int b,int &x,int &y){ if(b==0) { x = 1; y = 0; return a; } int r = exGcd(b,a%b,x,y); t = x; x = y; y = t-a/b*y; return r;} 按照惯例再说两句

本人蒟蒻一枚,博客难免有误,发现错误的大牛牪犇可以发私信联系本人指正错误。另外本博客可能会更新,可以考虑收藏一下。
好了,暂时就讲这么多了,如果绝对这里讲解得不够详细,也可以私信联系本人交流一下。
欢迎转载,转载请说明出处,谢谢。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。