文章目录
数论最大公约数最小公倍数*裴蜀定理质数单个质数的判断质数筛埃氏筛*欧拉筛
华为OD算法/大厂面试高频题算法练习冲刺训练
数论
最大公约数
对于正整数
A
A
A和
B
B
B而言,若正整数
X
X
X是同时能够被
A
A
A和$
整除的最大正整数,则称
整除的最大正整数,则称
整除的最大正整数,则称X
是
是
是A
和
和
和B$的最大公约数 (Greatest Common Divisor,GCD)
一般使用辗转相除法来求两个数的最大公约数,其流程如下
规定两个数中的较大值和较小值分别为
A
A
A和
B
B
B,然后进行循环计算
X
=
A
%
B
X=A\%B
X=A%B,其中
%
\%
%为求余符号若此时
X
=
0
X=0
X=0,则此时
B
B
B是两数之间的最大公约数,退出循环若此时
X
≠
0
X\neq0
X=0,则需要将
B
B
B是两数赋值给
A
A
A,余数
X
X
X赋值给
B
B
B,重复第二步
上述过程用代码表示为
def get_gcd(A, B):
A, B = max(A,B), min(A,B)
while A % B != 0:
X = A % B
A = B
B = X
return B
A, B = 144, 60
print(get_gcd(A, B)) # 输出12
在python中,math库中自带的gcd()函数,也可以直接计算两个数的最大公约数,其代码为
from math import gcd
A, B = 144, 60
print(gcd(A, B)) # 输出12
最小公倍数
对于正整数
A
A
A和
B
B
B而言,若正整数
Y
Y
Y是同时能够整除
A
A
A和
B
B
B的最小正整数,则称
Y
Y
Y是
A
A
A和
B
B
B的最小公倍数(Lowest Common Multiple,LCM)
已知一个正整数
A
A
A和
B
B
B的最大公约数为
X
X
X,最小公倍数为
Y
Y
Y,那么以下关系成立
X
∗
Y
=
A
∗
B
X*Y=A*B
X∗Y=A∗B
故求出正整数
A
A
A和
B
B
B的最大公约数为
X
X
X,就可以求出最小公倍数
Y
Y
Y。
Y
=
A
∗
B
X
Y=\frac{A*B}{X}
Y=XA∗B
用代码表示为
from math import gcd
A, B = 144, 60
print(A * B // gcd(A, B)) # 输出720
*裴蜀定理
裴蜀定理,也称为贝祖定理(Bézout’s identity),指的是对于任意两个非零整数 a 和 b,存在整数 x 和 y,使得 ax + by = gcd(a, b)。
这个定理表明,对于任意两个整数,其最大公约数可以由它们的线性组合表示。其中,x 和 y 是整数系数,可以是正数、负数或零。
举个例子。考虑两个整数 a = 42 和 b = 30。a 和 b 的最大公约数为gcd(42, 30) = 6
那么我们可以找到(x, y) = (2, -3),使得42x + 30y = 6成立。
题目LeetCode1250. 检查「好数组」就用到了裴蜀定理。我也贡献了一篇精华题解,感兴趣的同学可以看看这题。
质数
如果一个大于
1
1
1的正整数
X
X
X的因数只有
1
1
1和他自身,那么称
X
X
X为质数或素数(prime),否则称为合数(composite)。
特别规定:最小的质数是
2
2
2。正整数
0
0
0和
1
1
1既不是质数也不是合数。
单个质数的判断
要判断一个正整数
X
X
X是否为质数,最简单的方式就是枚举2到X-1的每一个数,检查这些数是否可以被
X
X
X整除。如果出现了任何一个数可以被
X
X
X整除,那么
X
X
X是一个合数;反之
X
X
X是一个质数。这种方法叫做试除法。
其代码实现如下
# 初始化一个标志,表示默认x是一个质数
isPrime = True
# 枚举从2到x-1的每一个数
for i in range(2, x):
# 如果x可以整除i,说明x是合数
if x % i == 0:
isPrime = False
break
# 退出循环后,根据isPrime的结果,可判断x是否是一个质数
上述过程的时间复杂度为O(x)。
实际上,由于一个正整数的因数总是成对出现的,无需枚举2到X-1的每一个数,只需要枚举枚举2到sqrt(X)就可以了。其证明如下:
假设
X
X
X 是一个正整数且是合数,即
X
X
X 可以被分解为两个正整数
a
a
a 和
b
b
b,其中
1
<
a
≤
b
<
X
1
1
X \sqrt{X} X ,另一个数一定大于等于 X \sqrt{X} X ,即 1 < a ≤ X ≤ b < X