../数论
./欧几里得算法(辗转相除法)
可以用来求最大公约数 除此之外短除法一可以求
欧基里德算法原理动态图这里就不展示了
请自行 去wiki官网搜索Euclidean algorithm 里面就有该gif图,特别清晰 ,属于很好的数形结合
1.1 基本知识:
-
公约数 定义:如果
d|a
(d 整除 a)且d|b
,那么 d 是 a 与 b 的 公约数。 性质:如果d|a
且d|b
,那么d|(ax + by); x,y ∈ Z(任意整数)
-
最大公约数 定义:两个非零整数 a 和 b 的公约数里最大的就是 最大公约数。
1.2 相关等式跟推论:
-
等式 1:如果
a|b 且 b|a
那么a = ±b
-
等式 2:如果
d|a 且 d|b
那么d|(ax + by); x,y ∈ Z
-
等式 3:
a mod n = a - n⌊a/n⌋(向下整除); a∈Z,n∈N*(正整数)
-
推论 1:对任意整数 a , b,如果
d|a 且 d|b
则d|gcd(a, b)
如果我们想要获得结论gcd(a,b) = gcd(b, a mod b)
那么我们只需要证明gcd(a,b)|gcd(b, a mod b) 且 gcd(b,a mod b)|gcd(a,b)
就可以利用等式 1来证明他俩相等了。
2.1 证明 gcd(a,b)|gcd(b,a mod b)
设
d = gcd(a, b)
∴d|a 且 d|b
∵ 由 等式 3 可知:(a mod b) = a - qb
q = ⌊a/b⌋
∴a mod b
是 a 与 b 的线性组合 ∴ 由 等式 2 可知 :d|(a mod b)
∵d|b 且 d|(a mod b)
∴ 由 推论 1 可知d|gcd(b, a mod b)
等价结论:gcd(a, b)|gcd(b, a mod b)
2.2 证明 gcd(b,a mod b)|gcd(a,b)
设
c = gcd(b, a mod b)
∴c|b 且 c|(a mod b)
∵a = qb + r
r = a mod b
q = ⌊a/b⌋
∴ a 是 b 和 (a mod b) 的线性组合 ∴ 由 等式 2 可知:c|a
∵c|a 且 c|b
∴ 由 推论 1 可知:c|gcd(a, b)
等价结论:gcd(b, a mod b)|gcd(a, b)
s
2.3 证明 gcd(a,b) = gcd(b, a mod b)
由 上述两个结论 可知:
gcd(a, b)|gcd(b, a mod b)
gcd(b, a mod b)|gcd(a, b)
∴ 由 等式 1 可知: gcd(a, b) = gcd(b, a mod b)
到这里 GCD递归定理 就证明结束了
3.代码实现
循环(所有循环都可以写为递归)
改图为逻辑先把b赋值给a(大的数),再把求余后把余数复制给b(小的数),然后再求余,以此类推
int gcd(int a,int b)
{
int tmp; //余数
while(tmp!=0){
tmp=a%b;
a=b;
b=tmp;
}
return a;
}
递归
int gcd(int a,int b)
{
if(b==0)
return b;
else
gcd(b,a%b);
}
//或者下面
int gcd(int a,int b)
{
return b==0?b:gcd(b,a%b);
}
位运算
// 一般
int gcd(int a, int b) {
while(b) {
a %= b;
// 交换 a 跟 b 的值
b ^= a;
a ^= b;
b ^= a;
}
return a;
}
// 简化
int gcd(int a, int b) {
while(b^=a^=b^=a%=b);
return a;
}