首页 > 代码库 > 扩展欧几里德算法
扩展欧几里德算法
本来数学就不好,看到LRJ的数学专题直接跪了,上网百度了一下才知道扩展欧几里德算法的证明过程。
首先说一下朴素欧几里德算法,就是辗转相除法,很简单。
int gcd(int a,int b){ return b == 0 ? a : gcd(b,a % b); }
下面主要说一下扩展欧几里得算法。
给出a,b 求 x,y使得 a * x + b * y = gcd(a,b);
我们不妨设a > b,且 x > y
那么当b = 0 的时候 gcd(a,b) = a,因此 x = 1 , y = 0;
如果b != 0 的时候,我们知道
ax1 + by1 = gcd(a,b) = bx2 + (a % b)y2;(根据朴素欧几里德)
我们化简一下这个式子
ax1 + by1 = bx2 + (a - (a / b) * b)y2;
ax1 + by1 = bx2 + a * y2 - (a / b) * b * y2;
ax1 + by1 = a * y2 + b * (x2 - (a/b) * y2);
因此 x1 = y2;
y1 = (x2 - (a/b) * y2);
也就是说每一层的x,y可以由上一层的x,y求出,递归终点为 b = 0;
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<map> #include<set> #include<list> #include<string> #include<cmath> #include<sstream> #include<ctime> using namespace std; #define _PI acos(-1.0) #define INF 1 << 10 #define esp 1e-6 typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> pill; /*=========================================== ===========================================*/ void gcd(int a , int b , int & d,int &x ,int &y){ if(!b){ d = a; x = 1; y = 0; } else{ gcd(b , a % b ,d, y , x); y -= x * (a / b); } } int main(){ int x,y,a,b,c; while(scanf("%d%d",&a,&b) != EOF){ x = max(a,b); y = x; if(a < b) /*保证a > b */ swap(a,b); gcd(a,b,c,x,y); /*代表a * x + b * y = c */ printf("(%d * %d) + (%d * %d) = %d\n",a,x,b,y,c); } return 0; }
ps:另外,要求多组解的话,假设已经求了一组解为(x0,y0),设:a‘ = a / gcd(a,b), b‘ = b / gcd(a,b),那么其余任意解都可以写成(x0 + k * b‘ ,y0 - k * a‘);
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。