1.欧几里德(辗转相除法)
用处:求a,b 两个数最大的公约数
利用递归来实现,或者在主函数中用循环实现
代码
#include<stdio.h>
int gcd(int a,int b)
{
if(a%b==0)
return b;
else
return gcd(b,a%b);
}
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("max:\n");
printf("%d\n",gcd(a,b));
return 0;
}
2.扩展欧几里德 (注:x(n)n代表下表,下面都是如此)
方程式ax+by=c,已知a,b,c,求x,y?
扩展欧几里德中c要是gcd(a,b)的倍数,才会有整数解
为什么一定要等于最大公约数呢?
//本质a 和b是互质的(互质:代表两个数最大公约数为1) 并且最大公约数为1;
//例如 2x+4y=1;是求不出来的;如果2x+4y=2 就是成立的 因为2(x+2y)=2 --x+2y=1 是可以转变的
//ax+by=d;
//a=m*d;b=n*d;
//m*d*x+n*y*d=d;
//mx+ny=1;
//所以互质情况下d就为1,他们可以同时扩大倍数,就像刚刚上面举的2x+4y=2这个例子;
c如果不是d的倍数就没有整数解,但是可以有小数解;
因为ax+by=gcd(a,b),所以设他们的最大公约数为d
所以ax+by=d
根据欧几里德得知:gcd(a,b)=gcd(b,a%b)
gcd(a,b)=gcd(b,a)
b*x1+a%b*y1=d;
所以b*x1+a-[a/b]/b*y1=d
所以x=y1;y=x1-a/b*y1;
递归下去直至b=0,a就是最大公约数;
所以 d*x(n)+0*y(n)=d;
所以x(n)=1,y(n)任意 推出他之前的x(n-1)和y(n-1);
直至推出x和y;
代码:例如青蛙约会的题POJ 1061
<p>#include<stdio.h>
long long m,n,l,y,x,k;
long long X,Y,a,b,c,t,d;</p><p>int extend_gcd(int a,int b)
{
if(b==0)
{
X=1;
Y=0;
return a ;
}
d=extend_gcd(b,a%b);
t=X; //用t来保存本次的x,因为下面的会变
X=Y;
Y=t-(a/b)*Y;
return d;
}
int main()
{
scanf("%d%d%d%d%d",&x,&y,&m,&n,&l);
a=m-n;
b=-l;
c=y-x;
d=extend_gcd(a,b);
if(c%d!=0)
{
printf("Impossible\n");
return 0;
}
X=X*(c/d);
Y=Y*(c/d);
//X=X+k(b/d); //使通解最小 通解见下面解释
k=X/(b/d); // k应与x符号相反
X=X-k*b/d;
if(X<=0) X+=b/d;
printf("%lld",X);</p><p>
return 0;
}
</p>
因为把c变成了d,所以c=d*(c/d);
x 和 y 都* c/d;
求出一组x和y就能求出他的通解
ax+m+by-m=c;
m是ab的最小公倍数,m=a*b/d; //最小公倍数是两个数相乘除以最大公约数
为什么是最小公倍数,因为要使m/a是整数并且最小;
使x的跨步小;
a*(x+m/a)+b(y-m/b)=c;
所以
a(x+b/d)+b(y-a/d)=c
通解就为
x0=x0+k*b/d;
y=y0-k*a/d;