引言
本部分内容主要针对算法中可能遇到的数学问题。大多都是属于轮子,作为一个工具使用。
数论
质数的判定
采用试除法,时间复杂度是 O ( n ) O(\sqrt{n}) O(n)
def isprime(x):
if x<2:
return Fasle
i = 2
while i<=n/i:
if x%i == 0:
return False
i += 1
return True
分解质因数
试除法,时间复杂度 O ( log ( n ) ) O(\log(n)) O(log(n))~ O ( n ) O(\sqrt{n}) O(n)
# 计算质因数的个数
def divide(x):
ans = 0
i = 2
while i<=n/i:
if x%i == 0:
# 找到了质因数就一直分解,直到不存在这个质因数
while x%i == 0:
x /= i
ans += 1
i += 1
if x>1: # 特判大于根号n的质因数
ans += 1
埃氏筛法求质数 ——首选
每次在删除倍数时候,只删除质数倍的。
时间复杂度:
O
(
n
log
log
n
)
O(n\log\log n)
O(nloglogn)
# 计算[1,x]中的全部质数
def get_prime(x):
ans = []
has = [0]*(x+1) # 已经被筛掉
for i in range(2, n+1):
if has[i] == 0:
ans.append(i)
for j in range(2*i, n+1):
has[j] = 1
return ans
线性筛求质数
时间复杂度
O
(
n
)
O(n)
O(n)
线性筛法:把每个和数用它的某一个质因子筛掉 大概比埃氏筛法快一倍
n只会被它的最小质因子筛掉
- 1
i%primes[j] == 0
primes[j]
一定是i的最小质因子,也一定是primes[j]*i
的最小质因子 - 2
i%primes[j] != 0
primes[j]
一定小于i的所有质因子,也一定是primes[j]*i
的最小质因子
# 计算[1,x]中的全部质数
def get_prime(x):
ans = []
has = [0]*(x+1) # 已经被筛掉
for i in range(2, n+1):
if has[i] == 0:
ans.append(i)
j = 0
while ans[j] <= n/i:
has[ans[j]*i] = 1
if i % ans[j] == 0: # 说明pj一定是i的最小质因子,pj也一定是pj*i的最小质因子
break
j += 1
return ans
求所有的约数
def get_divisors(x):
i = 1
ans = []
while i <= n/i:
if x%i == 0:
ans.append(i)
if i != n/i:
ans.append(n/i)
i += 1
ans.sort()
return ans
约数个数和约数之和
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和:(p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)