欧几里得算法
【辗转相除法求GCD】
欧几里得法求GCD效率较辗转相减法求GCD而言效率要高得多。
算法原理:gcd(a,b)=gcd(b,a mod b)
首先我们可以假设a=k∗b+ra=k∗b+r(其中的r代表着a/b的余数,也就是a%b的结果)
1.首先我们假设d是a和b的最大公约数,则我们可以知道 a可以整除d,表示为a|b,b也可以整除d,表示为b|d,由于r=a−k∗br=a−k∗b 其中a是d的倍数,而且b也是d的倍数,那我们可以得到其实r也是d的倍数,换句话说r也是可以整除d.
2.接下来我们假设d是b和r的最大公约数,则我们可以知道b可以整除d,表示为b|d,r也可以整除d,表示为r|d,由于a=k∗b+ra=k∗b+r其中b是d的倍数,而且r也是d的倍数,那我们可以得知其实a也是d的倍数,换句话说a也是可以整除d.
通过以上的充分必要式的证明方法,我们可以得到:gcd(a,b)=gcd(b,a%b)
【gcd模板】
int gcd(int a, int b){ if(b == 0) return a; return gcd(b, a%b); }
【扩展欧几里得算法】
解决问题:ax + by = gcd(a,b)的一组整数解x0 y0
算法原理:
(1)当b = 0时,很显然 x = 1,y = 任意整数。不妨x = 1, y = 0
(2)设 bx' + (a%b) y' = gcd(b , a%b)
由欧几里得算法:gcd(a,b)=gcd(b,a%b)
从而:ax + by = bx' + (a%b) y'; 即 ax + by = bx' + (a - a/b*b)y'
整理成关于a,b的不定方程:ax + by = ay' + b(x' - a/by'),系数对应相等得到:
x = y' ;
y = x' - a/by'
试想:如果不断迭代下去,直至b = 0,然后运用(1)的结果直接得到(x' = 1, y '= 0)反推回去,是不是就能够得到初始的x,y的值了?
int ex_gcd(int a,int b,int &x,int &y) { if(b == 0) { x = 1; y = 0; return a; } int r = ex_gcd(b,a%b,x,y);
int t = x;//保存上一次的x' x = y;//本次的x是上一次的y' y = t - a/b*y;//本次的y是上一次的x' - a/b*y'
return r; }
【定理总结】
(1)二元一次不定方程 ax + by = k有解的充要条件是 gcd(a,b) | k
(2)若ax + by = gcd(a,b)的一组特解是x0 ,y0,则通解:
x = x0 + b/gcd(a,b) * t ;
y = y0 - a/gcd(a,b) * t ,
方程ax + by = k的解是x,y乘上 k/gcd(a,b),即x = (x0 + b/gcd(a,b) * t) * k/gcd(a,b)
(3)要求方程ax + by = k的x的最小正整数解,则先求一个x0,y0,令p = b/gcd(a,b)
然后令 x = (x0 + p)* k/gcd(a,b), x = (x%p + p)%p.对应的y =(k - a*x) / b
【例题】
poj2142