简单写一下最大公约数: 对一个整数a来说,如果存在x使得a % x = 0(a除x,除得的商正好是整数而没有余数),就说x是a的约数,比如12的约数有1, 2,3,4,6,12
那两个数的最大公约数就是两个数a,b的公共的约数中最大的那个,如6的约数有1,2,3,6,那么6和12的最大公约数就是6; 8的约数有1,2,4,8,那么8和12的最大
公约数就是4.多个数的扩展就不说了.用得多的就是两个数之间的:
typedef long long ll;
ll gcd(ll a, ll b) {
if (b) return a;
return gcd(b, a%b);
}//欢迎拿去用,这写法简洁,而且绝对正确!
进入主题,扩展欧几里得:
/*
* (1) source: 求整数x,y使得ax+by=1
* 推导:如果gcd(a,b)!=1,那么不妨设gcd(a,b)=k(k>1)则原式变成k(x*(a/k) + y*(b/k))=1,其中由于
* k是a,b公约数,a/k,b/k依然是整数,可以相见,一个大于1的整数乘以另一个整数是不可能等于1的,
* 回到刚才,我们可以知道要使ax+by=1 必须有gcd(a,b)=1**********(1)
* (2)事实上,一定存在整数对(x,y)使得ax+by=gcd(a,b),如果另gcd(a,b)等于1,就可以导出过程(1)
* 设int extgcd(int a, int b, int& x, int& y)是求解该方程的函数,返回值为gcd(a,b).和gcd的定义:
* int gcd(int a, int b) {
* if (!b) return a;
* return gcd(b, a%b);
* }
* 一样,我们可以递归地定义extgcd.
* 假设已经求得了: bx'+(a%b)y'=gcd(a,b)的整数解x'和y'.再将a%b=a-(a/b)*b代入后就得到:
* ay'+b(x'-(a/b)*y')=gcd(a,b)
* 而当b=0时则有a*1+b*0=a=gcd(a,b)
* 将上述过程转化成代码就是:
* int extgcd(int a, int b, int& x, int& y) {
* int d = a;
* if (b != 0) {
* d = extgcd(b, a % b, y, x);
* y -= (a / b) * x;
* } else {
* x = 1; y = 0;
* }
* return d;
* }
* by. *花式*小冬摘自<<挑战程序设计竞赛>>
*/
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;
/****************************************/
typedef long long ll;
const int MAX = 7401;
/* ax + by = gcd(a,b) */
ll extgcd(int a, int b, int& x, int& y) {
int d = a;
if (b) {// --> if (b != 0) {
d = extgcd(b, a%b, y, x);
y -= (a/b) * x;
} else {
x = 1; y = 0;
}
return d;
}
int main() {
int a, b, x, y;
srand(unsigned(time(0)));//用系统当前时间为随机数种子
while (!cin.eof()) {
a = rand()%MAX;
b = rand()%MAX;//随机生成a,b,其实我们完全可以筛选掉负数,但是没关系,这里看看就好了
int _gcd = extgcd(a, b, x, y);
printf("(%d, %d) matchs %d*%d + %d*%d = %d\n", x, y, a, x, b, y, _gcd);
puts("......................................");
cin.clear();
cin.get();
}
return 0;
}