求解证明的方法比较麻烦 为了方便理解我也前后写了不少 今天才完成
关于扩展欧几里德算法主要是证明理解方面要花功夫 下面先给网络上大牛的文章
网上大牛的博文:http://www.cnblogs.com/comeon4mydream/archive/2011/07/18/2109060.html
百度百科:http://baike.baidu.com/view/1478219.htm
以下是我自己对整个过程的总结
我们先了解下欧几里德算法:
欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。
gcd(a,b) 表示 a,b的最大公约数,一般程序里也用同名函数来计算最大公约数
计算原理如下:(b不为0时 且a和b不相等的情况下)
我们设gcd(a,b)=d
再设a除以b的余数为r1 并且必有r1<b
那么必然有非负整数x0使得a=b*x0+r1等式成立 可变为r1=a-b*x0
那么r1必然也是d的倍数 这样就有a b r1的最大公约数为d
就是说 d=gcd(a,b)=gcd(b,r1)
如此我们再设b除以r1的余数为r2 并且必有r2<r1
那么必然有非负整数x1使得b=r1*x1+r2等式成立 可变为r2=b-r1*x1
那么r2必然也是d的倍数 这样就有a b r1 r2的最大公约数为d
就是说 d=gcd(a,b)=gcd(b,r1)=gcd(r1,r2) 其中 b>r1>r2
这样反复我们就会得出 d=gcd(a,b)=gcd(b,r1)=gcd(r1,r2)=……=gcd(rn-1,rn) 其中 b>r1>r2>……>rn-1>rn=d
那么必然有非负整数xn-1使得rn-2=(rn-1*xn-1) +rn等式成立 可变为rn=rn-2 -(rn-1*xn-1)
然后我们发现rn-1除以rn其余数就为0 这就可以判断rn为最大公约数d
这就是欧几里德算法求最大公约数的算法了(上述算法当a=b的时候我们可知最大公约数就为其本身同样适用
我们通过程序来求解就有:
int Gcd(int a, int b)
{
if(b == 0) return a;
return Gcd(b, a % b);
} // 递归形式
以上就是欧几里德算法程序实现方法
然后我们就可以开始了解扩展欧几里德算法了
此算法常用来求解二元一次不定方程 a*x+b*y=c 的整数解
(其中a b c均为整数,不为整数的话我们也可以同乘一个系数来使其都变为整数)
我们先从特殊入手 假设c=d=gcd(a,b)这样方程可以写成
上面解说的时候我们知道求解d的过程 其中间量rn=rn-2 -(rn-1 * xn-1)
其中xn-1=(rn-2)/(rn-1)( 注意这里是计算机的的除法就是结果向下取整)于是有下面一组式子
rn=rn-2 -(rn-1 * xn-1)
我们把第一个式子d= rn= rn-2 –(rn-1 * xn-1)改写为d=rn=ln*rn-1 +kn*rn-2
我们代入rn-1=rn-3 –(rn-2*xn-2)有d=rn= (kn– ln*xn-2)*rn-2 +ln*rn-3
我们再次改写为d=rn=ln-1*rn-2 + kn-1*rn-3
有了这个递推公式我们就不断推导求出这个式子d=rn=l1*b+k1*a
那么我们可以说a*x+b*y=gcd(a,b)=d 必有整数解
而且x=k1+t*b/gcd(a,b) 、y=l1-t*a/gcd(a,b)
(对于这个解通式
我们扩大c的范围为gcd(a,b)*c0 即c=gcd(a,b)*c0=d*c0
方程改写为为a*x+b*y=d*c0 (c0为整数)
有a*x0+b*y0=d 转化为求x0和y0
并且x=x0*c0 + t*b/gcd(a,b) 、y=y0*c0 - t*a/gcd(a,b)
我们再次扩大c的范围对于任意的a*x+b*y=c我们可以求得d=gcd(a,b)
并且设a/d=a0
等式右边只有当c%d==0的时候才可为整数
如果c%d!=0 即c/d为小数 那么没有整数对x y可以让等式左边成为小数 自然不可能有整数解
于是 c%gcd(a,b)==0 是方程a*x+b*y=c有整数解的充分必要条件
有了上面的证明 我们就可以来解二元一次不定方程的整数解了
方程a*x+b*y=c
如果c%d!=0 那么肯定无整数解
计算整数c0=c/d
再用x=x0*c0
如此我们就可以计算整数解x0和y0最后乘以c0
为了方便计算我们用a0=a/d
然后通过欧几里得算法求gcd(a0,b0)(也可以求gcd(a,b) 不会影响结果)的过程
求出中间变量ln=-xn-1
最后求得x0=k1
接下来通过程序来实现这个过程
已知a
求d=gcd(a,b)
然后判定c%d是否为0
若为0
当然我们在递归求d的时候
程序如下
int
int gcd(int a, int b)
{
}
递归结束后我们就得到了最后的k和l
最后的结果(y解同样 我就懒得写了)为
如果求最小正整数解
对于x 在区间范围
证明如下: 在区间范围[0,b/gcd(a,b)-1]内
我们可以带入解的通式 0<= k* c/gcd(a,b)+t* b/gcd(a,b) < b/gcd(a,b)
t在一个区间宽度只有1的范围内取值 有且仅有一个整数值 使其在区间范围[0,b/gcd(a,b)-1]有整数解
自然求解的方法也出来了:计算-k*c/b 向上取整求得t
关于此类问题 还有一些变形和特殊条件 但是方法类似
下面附上专题训练
http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=5378
要求:都要完成 并且完成一题从头写另一题 不要改改原代码就提交另一题 一定要练习到完全掌握核心思想