
图:暴力?NO!数学做法,降维打击!
本文整理了力扣上的数学相关题目,主要以数论和组合数学为主。
部分题目(尤其是组合数学)会涉及到取模,我写了一篇教程,请看 模运算的世界:当加减乘除遇上取模。
模板:
# 时间复杂度 O(sqrt(n))
def is_prime(n: int) -> bool:
for i in range(2, isqrt(n) + 1):
if n % i == 0:
return False
return n >= 2 # 1 不是质数模板(埃氏筛):
# 时间复杂度 O(MX * log log MX)
MX = 1_000_001
is_prime = [False] * 2 + [True] * (MX - 2) # 0 和 1 不是质数
primes = []
for i in range(2, MX):
if is_prime[i]:
primes.append(i)
for j in range(i * i, MX, i):
is_prime[j] = False # j 是质数 i 的倍数模板一,预处理每个数的所有不同质因子。原理同埃氏筛。
MX = 1_000_001
prime_factors = [[] for _ in range(MX)]
for i in range(2, MX):
if not prime_factors[i]: # i 是质数
for j in range(i, MX, i): # i 的倍数 j 有质因子 i
prime_factors[j].append(i)模板二,预处理 的最小质因子 ,从而做到 分解 。可以求出 的每个质因子的个数。
MX = 1_000_001
lpf = [0] * MX
for i in range(2, MX):
if lpf[i] == 0: # i 是质数
for j in range(i, MX, i):
if lpf[j] == 0: # 首次访问 j
lpf[j] = i
# 质因数分解
# 例如 prime_factorization(45) = [(3, 2), (5, 1)],表示 45 = 3**2 * 5**1
# 时间复杂度 O(log x)
def prime_factorization(x: int) -> List[Tuple[int, int]]:
res = []
while x > 1:
p = lpf[x]
e = 1
x //= p
while x % p == 0:
e += 1
x //= p
res.append((p, e))
return res模板(预处理每个数的所有因子):
# 预处理每个数的因子
MX = 1_000_001 # **根据题目调整**
divisors = [[] for _ in range(MX)]
for i in range(1, MX):
for j in range(i, MX, i): # 枚举 i 的倍数 j
divisors[j].append(i) # i 是 j 的因子部分语言的标准库没有 GCD 和 LCM,需要手写。推荐写迭代,比递归快一点。
class Solution {
private long gcd(long a, long b) {
while (a != 0) {
long tmp = a;
a = b % a;
b = tmp;
}
return b;
}
// 推荐先除后乘,尽量避免溢出
private long lcm(long a, long b) {
return a / gcd(a, b) * b;
}
}快速幂、组合数的预处理模板见 模运算的世界:当加减乘除遇上取模
关于生成函数的题目,见本题单的「§2.6 生成函数」。
思维扩展:
部分题目有其他解法,难度分仅供参考。
思维扩展:
随机数据下显著更快的算法:
另见 动态规划题单 的「§11.7 斜率优化 DP」。
从小到大枚举回文数的模板(从 开始枚举):
def gen_palindrome() -> Iterator[int]:
base = 1
while True:
# 生成奇数长度回文数,例如 base = 10,生成的范围是 101 ~ 999
for i in range(base, base * 10):
s = str(i)
x = int(s + s[::-1][1:])
yield x
# 生成偶数长度回文数,例如 base = 10,生成的范围是 1001 ~ 9999
for i in range(base, base * 10):
s = str(i)
x = int(s + s[::-1])
yield x
base *= 10
for x in gen_palindrome():
if x > 10 ** 9: # 根据题目调整
break
# 处理 x 的逻辑写下面
print(x)另见本题单的「§2.6 生成函数」。
见 位运算题单。
欢迎关注 B站@灵茶山艾府
如果你发现有题目可以补充进来,欢迎评论反馈。