1. 最大公约数
a a a 和 b b b 的最大公约数用 g c d ( a , b ) gcd(a,b) gcd(a,b) 表示
最大公约数基本上有这几种算法,分别是:
- 暴力,复杂度 O ( m i n ( a , b ) ) O(min(a,b)) O(min(a,b))
- 利用 九章算法 · 更相减损术 g c d ( a , b ) = g c d ( a − b , b ) gcd(a,b)=gcd(a-b,b) gcd(a,b)=gcd(a−b,b) ,不断缩小数据,边界条件是 g c d ( a , 0 ) = a g c d ( 0 , b ) = b gcd(a,0)=a\ gcd(0,b)=b gcd(a,0)=a gcd(0,b)=b
- 利用欧几里得发现的 g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a,b)=gcd(b,a \mod b) gcd(a,b)=gcd(b,amodb) 边界条件也是一样
因为第三种数据缩小的最快,所以使用第三个,其利用第二个多来几次就可以,这里给另一种证明:
当 a < b a \lt b a<b , a m o d b = a a \mod b=a amodb=a ,所以 g c d ( a , b ) = g c d ( b , a ) = g c d ( b , a m o d b ) gcd(a,b)=gcd(b,a)=gcd(b,a \mod b) gcd(a,b)=gcd(b,a)=gcd(b,amodb)
当 a ≥ b a \ge b a≥b ,设 a = q b + r a=qb+r a=qb+r ,其中 0 ≤ r < b 0 \le r \lt b 0≤r<b (其实就是 a / b a/b a/b 的商和余数),设 g = g c d ( a , b ) g=gcd(a,b) g=gcd(a,b)
r = a m o d b r=a \mod b r=amodb
∵ g ∣ a , g ∣ b \because g \mid a,\ g \mid b ∵g∣a, g∣b
∴ g ∣ q b + r , g ∣ q b \therefore g \mid qb+r,\ g \mid qb ∴g∣qb+r, g∣qb
∴ g ∣ r \therefore g \mid r ∴g∣r
∴ g ∣ a m o d b \therefore g \mid a \mod b ∴g∣amodb
∵ a m o d b < b \because a \mod b \lt b ∵amodb<b
∴ g = g c d ( b , a m o d b ) \therefore g=gcd(b,a \mod b) ∴g=gcd(b,amodb)
于是我们可以这样求最大公约数;
int gcd(int a, int b)
{
if(b==0)return a;
return gcd(b, a%b);
}
我们也可以用循环实现:
int gcd(int a, int b)
{
if(a<b)swap(a, b);
while(b)
{
a%=b;
swap(a, b);
}
return a;
}
这是最常用的方法,当然还有一个针对高精度数据的方法
二进制算法
对于两个数 a , b a,b a,b ,当 a = b a=b a=b 时 , gcd ( a , b ) = a \gcd(a,b)=a gcd(a,b)=a
否则,当 a , b a,b a,b 都是偶数时 , gcd ( a , b ) = 2 × gcd ( a 2 , b 2 ) \gcd(a,b)=2 \times \gcd(\frac{a}{2},\frac{b}{2}) gcd(a,b)=2