gcd
的概念
gcd
是指最大公约数,如gcd(6, 4)
就是指6和4的最大公约数,结果显然是2。
辗转相除法
辗转相除法:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数,即 g c d ( a , b ) = g c d ( b , a % b ) ( a > b 且 a % b ≠ 0 ) gcd(a, b) = gcd(b, a \% b)\qquad (a > b且a \% b \neq 0) gcd(a,b)=gcd(b,a%b)(a>b且a%b=0)
证明:
不妨设 d = g c d ( a , b ) d = gcd(a, b) d=gcd(a,b)
那么一定存在正整数m和n使得 a = n d , b = m d a=nd, b=md a=nd,b=md
令 r = a % b , k = ⌊ a b ⌋ r=a\%b,k=\lfloor\frac{a}{b}\rfloor r=a%b,k=⌊ba⌋
则 r = a − k b = ( n d ) − k ( m d ) = ( n − k m ) d r=a-kb=(nd)-k(md)=(n-km)d r=a−kb=(nd)−k(md)=(n−km)d
显然r同样可被d整除,d同样是b和r的公约数
假设t是b和r的公约数,显然t也是a和b的公约数
即a和b的公约数,与b和 a % b a\%b a%b的公约数是相同的,那么它们的最大公约数肯定也是相同的
代码:
int gcd(int x, int y){
if(y == 0) return x;//倘若y为0了,说明上一次x和y是相等的且都等于最大公约数
//上一次的y变成了这一次的x,那么我们直接返回x就好了
return gcd(y, x % y);
}
你也可以用三元操作符?:
来简化代码
int gcd(int x, int y){
return y ? gcd(y, x % y) : x;
}
在c++
中还有一个函数__gcd()
可以直接用来求最大公因数
cout << __gcd(x, y) << endl;
裴蜀定理
裴蜀定理:若a,b是整数,且 g c d ( a , b ) = d gcd(a,b)=d gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使 a x + b y = d ax+by=d ax+by=d成立。
裴蜀定理的证明:
对于任意的整数x,y,ax+by都一定是d的倍数
,这一点很容易证明。我们只证明后面的一定存在整数x,y,使ax+by=d成立
∵ d = g c d ( a , b ) ∴ d ∣ a , d ∣ b , ( 即 a 和 b 都 能 被 d 整 除 ) 设 s 为 a 和 b 的 线 性 组 合 的 最 小 正 值 , 不 妨 设 s = x a + y b 令 q = ⌊ a s ⌋ , r = a % s 则 r = a − q × ( x a + y b ) = ( 1 − q x ) a − ( q y ) b 显 然 r 同 样 是 a 和 b 的 线 性 组 合 , 且 0 ≤ r < s 但 我 们 已 经 假 设 了 是 s 是 a 和 b 的 线 性 组 合 的 最 小 正 值 ∴ r = 0 , 即 a % s = 0 ∴ s ∣ a , s ∣ b , ( 倘 若 不 理 解 为 什 么 s ∣ b 的 话 , 其 实 也 可 以 把 上 述 推 理 过 程 中 的 a 换 成 b ) 那 么 s 也 是 a 和 b 的 公 约 数 , 任 何 一 个 公 约 数 都 小 于