本来数学就不好,看到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‘);
原文:http://blog.csdn.net/u013451221/article/details/38487753