【算法专题讲解】数学问题

引言

本部分内容主要针对算法中可能遇到的数学问题。大多都是属于轮子,作为一个工具使用。

文章目录

  • 引言
  • 数论
    • 质数的判定
    • 分解质因数
    • 埃氏筛法求质数 ——首选
    • 线性筛求质数
    • 求所有的约数
    • 约数个数和约数之和
  • 组合计数
  • 高斯消元
  • 简单博弈论

数论

质数的判定

采用试除法,时间复杂度是 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)

组合计数

高斯消元

简单博弈论

你可能感兴趣的:(专题讲解)