复习一下解方程
0X00 解线性方程
用「高斯消元法」解线性方程
过程都写注释里面了,想一次写对真的挺难的
def gauss(n, mat):
eps, r = 1e-6, 0
for c in range(n):
# 找出该列的绝对值最大值
t = r
for i in range(r+1, n, 1):
if abs(mat[i][c]) > abs(mat[t][c]): t = i
# 把最大列所属的那一行交换到 r 行上,初等行变换
mat[t], mat[r] = mat[r], mat[t]
# 如果该列全为 0 则跳过这一列
if abs(mat[r][c]) < eps: continue
# 将所有数除以第一个数
for i in range(n, c-1, -1): mat[r][i] /= mat[r][c]
# 将下面所有的数字变为 0
for i in range(r+1, n, 1):
if abs(mat[i][c]) < eps: continue
for j in range(n, c-1, -1):
mat[i][j] -= mat[i][c] * mat[r][j]
r += 1
if r < n:
for i in range(n-1, r-1, -1):
if abs(mat[i][-1]) > eps: return 2
return 1
for i in range(n-1, -1, -1):
for j in range(n-1, i, -1):
mat[i][-1] -= mat[i][j] * mat[j][-1]
return 0
t = gauss(n, mat)
if t == 0:
for i in range(n): print("{:.2f}".format(mat[i][-1]))
elif t == 1:
print("Infinite group solutions")
else:
print("No solution")
与此相同的还有解异或线性方程
884. 高斯消元解异或线性方程组 基本一模一样
def gauss():
r = 0
for c in range(n):
# print(a)
t = -1
for i in range(r, n):
if a[i][c] == 1:
t = i
break
# print(r, t, a[t][c])
if t == -1: continue
a[t], a[r] = a[r], a[t]
for i in range(r+1, n):
if not a[i][c]: continue
for j in range(c, n+1):
a[i][j] ^= a[r][j]
r += 1
if r < n:
for i in range(r, n):
if a[i][-1]: return 2
return 1
for i in range(n-1, -1, -1):
for j in range(i+1, n):
a[i][n] ^= a[i][j] * a[j][n]
return 0
0X01 解不等式
可以用图论的方法解不等式,假设有 a, b 两个非负整数。无非就是以下五种情况
- a == b
- a > b
- a b
- a < b
- a b
放在图论中,我们有节点 a, b 如果有一条从 a 指向 b 的权重为 1 的边。那么就有 dist[b] > dist[a] + 1,如果有一条权重为 0 的边那么就有 dist[b] dist[a]。
因此,我们只需把不等式放在图论中,并建立一个虚拟原点,就能求出所有值的最大或最小值。比如这个题目:
求至少,就是求距离最大
。举个例子有两个合法的不等式: a > b 和 a b 我们最终取的也是 a > b。所以在计算距离的时候取的是最大值。
利用 spfa 计算所有点距离虚拟原点的距离。
def spfa(start):
dist = [float("-inf")] * (1+n)
dist[start] = 0
st = [False] * (1+n)
st[start] = True
q = [start]
cnt = [0] * (1+n)
while q:
v1 = q.pop()
st[v1] = False
for v2, w in g[v1]:
if dist[v2] < dist[v1] + w:
dist[v2] = dist[v1] + w
cnt[v2] = cnt[v1] + 1
if cnt[v2] >= n+1:
print(-1)
return
if not st[v2]:
q.append(v2)
st[v2] = True
# print(dist)
print(sum(dist))
网友评论