首先,所谓欧几里得定理,就是辗转相除法。
代码:
#include<bits/stdc++.h>
int a,b;
int gcd(int x,int y) {
if (y==0) return x;//别记反了!
return gcd(y,x%y);
}
int main(){
scanf("%d%d",&a,&b);
printf("%d\n",gcd(a,b));
return 0;
}
这是递归的。
#include<bits/stdc++.h>
int a,b;
int gcd(int x,int y) {
int r;
while (y) {
r=x%y;
x=y; y=r;
}
return x;
}
int main(){
scanf("%d%d",&a,&b);
printf("%d\n",gcd(a,b));
return 0;
}
这是非递归的。
然后我们可以用一种类似的方法解形如的不定方程,这就是扩欧了。
其实有一个问题,这个方程为什么有解呢?
这涉及到一个叫贝祖定理的东西,我们先不管它,假设一定有解。。。
那么,这个方程咋解呢?
要用到一种利用欧几里得定理的迭代的方法,大概是这样滴:
先列出两个形式与原方程一样的式子,
很显然,(都是求a和b的最大公约数)
于是乎:
我们知道:(整个数减去可以被整除的部分)
所以:
再把右边搞成a*...+b*...的形式:
瞧,现在两边形式一样了。
因为我们只要一组符合条件的解,所以只要让并且就可以了。
那怎么求呢,显然可以继续递归下去。
不难发现,a和b的值是一直在减小的(和辗转相除法一样,),边界条件也和辗转相除法一样,即。
那么当时会发生什么呢?(假如已经递归了n次)
显然,此时可取任何整数,不妨设为0(写123456也没事)。
然后就可以递归回去了,最后得到的一组解。
大功告成!
代码:
#include<bits/stdc++.h>
int a,b;
int x,y;
void ex_gcd(int a,int b) {
if (b==0) {
x=1;
y=0;//随便写其他整数值也可以
return ;//别忘返回了,不然进死循环爆系统栈
}
ex_gcd(b,a%b);
int tmp=x;
x=y;
y=tmp-a/b*y;
}
int main(){
scanf("%d%d",&a,&b);
ex_gcd(a,b);
printf("%d %d\n",x,y);
return 0;
}
解同余方程时是一样的(把模数看成b,给等式右边减去y个b),只不过要输出x的最小正整数解【洛谷P1082 同余方程】:
(wait!问题转化看这里)
#include<bits/stdc++.h>
int a,b;
int x,y;
void ex_gcd(int a,int b) {
if (b==0) {
x=1;
y=0;
return ;
}
ex_gcd(b,a%b);
int tmp;
tmp=x;
x=y;
y=tmp-a/b*y;
}
int main(){
scanf("%d%d",&a,&b);
ex_gcd(a,b);
while (x<0) x+=b;
printf("%d\n",x%b);
return 0;
}