欧几里得和扩展欧几里得算法

ゞ 浴缸里的玫瑰 2022-08-21 03:20 322阅读 0赞

(一)欧几里得算法又称辗转相除法,是求解两个数的最大公约数的算法,基本定义为:

a=qb+r,其中a,b,q,r都是整数,则:gcd(a,b)= gcd(b,r)

利用递归实现该算法:

  1. long long gcd(int a,int b)
  2. {
  3. if(b==0) return a;
  4. else return gcd(b,a%b);
  5. }

辗转相除法的应用:(水题)

nefu 116:两仪剑法http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=116

题目分析:

由题意知:该题是要求M和N的最小公倍数,由于数据较大,正常用会导致数据溢出而WA,所以要利用该求最小公倍数的公式变形,先去除,再去乘,来进行数据范围的控制,公式为:

Center

则代码实现如下:

  1. #include <iostream>
  2. #include <cstdio>
  3. using namespace std;
  4. long long gcd(int a,int b)
  5. {
  6. if(b==0) return a;
  7. else return gcd(b,a%b);
  8. }
  9. int main()
  10. {
  11. int m,n;
  12. while(scanf("%d%d",&m,&n)!=EOF)
  13. {
  14. printf("%lld\n",(m/gcd(m,n))*n);
  15. }
  16. return 0;
  17. }

(二)扩展欧几里得算法基本定义:

ab不全为0,则存在整数xy,使得 gcd(a,b)= xa + yb

拉梅定理:用欧几里得算法计算两个正整数的最大公因子时,所需的除法次数不会超过两个整数中较小的那个十进制数的倍数的5倍。

拉梅定理推论:求两个正整数a,b,a>b 的最大公因子需要O(log2a)3次的位运算。

由扩展欧几里得的推论:如果gcd(a,b)=1,则称ab互素。

整数a和b互素的充分必要条件:存在整数xy,使得xa+yb=1 。

扩展欧几里得算法实现:

  1. typedef long long int64;
  2. using namespace std;
  3. int64 exgcd(int64 m,int64 & x,int64 n,int64 & y) //Extend Euclid
  4. {
  5. int64 x1,y1,x0,y0;
  6. x0 = 1;y0 = 0;
  7. x1 = 0;y1 = 1;
  8. int64 r=(m%n+n)%n;
  9. int64 q=(m-r)/n;
  10. x=0;y=1;
  11. while(r)
  12. {
  13. x=x0-q*x1;
  14. y=y0-q*y1;
  15. x0=x1;
  16. y0=y1;
  17. x1=x;
  18. y1=y;
  19. m=n;
  20. n=r;
  21. r=m%n;
  22. q=(m-r)/n;
  23. }
  24. return n; //返回值为m和n的最大公约数,修改后的x和y的值是所求值
  25. }

扩展欧几里得算法应用:

POJ 1061:青蛙的约会 http://poj.org/problem?id=1061

题目分析:设两只青蛙跳了t步后相遇,A蛙的坐标为:x+mt ,B蛙的坐标为:y+nt 。两蛙相遇的条件为:Center 1 ,公式变形为:Center 2Center 3 ,求满足Center 4 的最小t(t>0),即求一次同余方程Center 5 的最小正整数解。具体求解过程为3步:

(1)写出方程Center 6,用扩展欧几里得函数求解,即Center 7 此时X是一个解,但不是最后的解。

(2)若(x-y)%gcd(n-m,L)==0, 则有解(指xy都有解)。

(3)有解后,设M=gcd(n-m,L),X=X(x-y)/M

然后:(X%(L/M)+(L/M))%(L/M) 就是最后的解,即为本题的t的值。

代码实现如下:

  1. #include <iostream>
  2. #include <cstdlib>
  3. typedef long long int64;
  4. using namespace std;
  5. int64 exgcd(int64 m,int64 & x,int64 n,int64 & y) //Extend Euclid
  6. {
  7. int64 x1,y1,x0,y0;
  8. x0 = 1;y0 = 0;
  9. x1 = 0;y1 = 1;
  10. int64 r=(m%n+n)%n;
  11. int64 q=(m-r)/n;
  12. x=0;y=1;
  13. while(r)
  14. {
  15. x=x0-q*x1;
  16. y=y0-q*y1;
  17. x0=x1;
  18. y0=y1;
  19. x1=x;
  20. y1=y;
  21. m=n;
  22. n=r;
  23. r=m%n;
  24. q=(m-r)/n;
  25. }
  26. return n; //返回值为m和n的最大公约数,修改后的x和y的值是所求值
  27. }
  28. int main()
  29. {
  30. int yy;
  31. int64 r,t;
  32. int64 x,y,m,n,l;
  33. int64 ar,br;
  34. cin>>x>>y>>m>>n>>l;
  35. int64 M=exgcd(n-m,ar,l,br);
  36. if((x-y)%M||m==n)
  37. cout<<"Impossible"<<endl;
  38. else
  39. {
  40. int64 s=l/M;
  41. ar=ar*((x-y)/M);
  42. ar=(ar%s+s)%s;
  43. cout<<ar<<endl;
  44. }
  45. return 0;
  46. }

发表评论

表情:
评论列表 (有 0 条评论,322人围观)

还没有评论,来说两句吧...

相关阅读

    相关 扩展算法

    poj 1061题目,青蛙的约会。一开始想暴力求解的。但是之前提交过,tle... 今天过来查一下,说是扩展欧几里得算法。我了个去。这么复杂的名字,得是有多深奥。 查了才知

    相关 扩展算法

    问题描述: 求解二元一次方程ax+by=c。 问题分析: 上述的二元一次方程可以用同余方程来进行描述:ax≡cmod(b) 两个问题可以进行转换,但是都可以用扩展的欧几

    相关 扩展

    GCD 定义 欧几里德算法又称辗转相除法,是指用于计算两个正整数a,b的最大公约数。 结论与证明 对于a,b两个正整数(a>b),gcd(a,b)=gcd(a