写在前面
一些可以直接调用的板子我都在下面给出,主要适用于蓝桥杯的Python选手。一些没有固定模板的写法在本文中不列出,如有紧张知识点遗漏,欢迎大家指出。
Python常用算法模板
快读
- import sys
- input = sys.stdin.readline
复制代码 影象化
- from functools import lru_cache
- @lru_cache(maxsize=None)
- def dfs(a, b):
- pass
复制代码 开递归深度
- import sys
- sys.setrecursionlimit(10**5)
复制代码 日期问题
常用库函数:
- from datetime import datetime # 日期时间
- from datetime import date # 日期
- from datetime import time # 时间
- from datetime import timedelta # 时间间隔
复制代码 有关日期天数的加减:
- d = datetime(2024, 4, 7) # 设置时间为2024年4月7日
- delta = timedelta(days=1) # 时间间隔为1天
- d_new = d + delta # d_new为2024年4月8日
复制代码 获取日期的年代日:
- d = datetime(2024, 4, 7) # 设置时间为2024年4月7日
- year = d.year() # 获取年
- month = d.month() # 获取月
- day = d.day() # 获取天
复制代码 进制转换
十进制转成其他进制:
- # 十进制转二进制
- bin(3) # 0b11
- # 十进制转八进制
- oct(8) # 0o10
- # 十进制转十六进制
- hex(255) # 0xff
复制代码 其他进制转十进制:
- # 二进制转十进制
- print(int('11', 2)) # 3
- # 八进制转十进制
- print(int('10', 8)) # 8
- # 十六进制转十进制
- print(int('ff', 16)) # 255
复制代码 前缀和模板
一维前缀和:
- a = [0, 1, 2, 3, 4, 5, 6, 7]
- prex = [a[0]]
- for i in range(1, len(a)):
- prex.append(prex[-1] + a[i])
- print(prex) # [0, 1, 3, 6, 10, 15, 21, 28]
复制代码 二维前缀和:
- n = 3 # 3*3的矩阵
- a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
- prex = [[0] * (n + 1) for _ in range(n + 1)]
- for i in range(1, n+1):
- for j in range(1, n+1):
- prex[i][j] = prex[i][j-1] + prex[i-1][j] - prex[i-1][j-1] + a[i][j]
- print(prex)
复制代码 差分模板
一维差分:
- a = [0] + [1, 3, 2, 5, 5, 6, 7, 9]
- diff = [0]
- for i in range(1, len(a)):
- diff.append(a[i] - a[i-1])
- print(diff) # [0, 1, 2, -1, 3, 0, 1, 1, 2]
复制代码 二维差分:
- n = 3 # 3*3的矩阵
- a = [[0, 0, 0, 0], [0, 1, 2, 3], [0, 4, 5, 6], [0, 7, 8, 9]]
- diff = [[0] * (n+1) for _ in range(n+1)]
- for i in range(1, n+1):
- for j in range(1, n+1):
- diff[i][j] = a[i][j] - a[i-1][j] - a[i][j-1] + a[i-1][j-1]
- print(diff) # [[0, 0, 0, 0], [0, 1, 1, 1], [0, 3, 0, 0], [0, 3, 0, 0]]
复制代码 在(x1,y1)到(x2,y2)的区间均加d
- diff[x1][y1] += d
- diff[x2+1][y2+1] += d
- diff[x1][y2+1] -= d
- diff[x2+1][y1] -= d
复制代码 离散化
- from bisect import bisect_left
- a = [1000, 2000, 900000, 3000, 4000]
- def discrete(li):
- tmp = sorted(set(a))
- new_li = []
- for i in range(len(a)):
- new_li.append(bisect_left(tmp, a[i]) + 1)
- return new_li
- print(discrete(a)) # [1, 2, 5, 3, 4]
复制代码 二分模板
- a = [1, 2, 3, 5, 5, 5, 6, 7, 9, 10]
- def bin_search_right(li, x):
- l, r = -1, len(li)
- while l + 1 != r:
- mid = (l + r) // 2
- if li[mid] <= x: l = mid
- else: r = mid
- return l
- # 找数组中最右边的值
- print(bin_search_right(a, 5)) # 5
复制代码- a = [1, 2, 3, 5, 5, 5, 6, 7, 9, 10]
- def bin_search_right(li, x):
- l, r = -1, len(li)
- while l + 1 != r:
- mid = (l + r) // 2
- if li[mid] >= x: r = mid
- else: l = mid
- return r
- # 找数组中最左边的值
- print(bin_search_right(a, 5)) # 3
复制代码 埃氏筛模板
- def get_prime():
- N = 100010
- flag = [0] * N
- for i in range(2, N):
- if flag[i] == 0:
- for j in range(i+i, N, i):
- flag[j] = 1
- prime = []
- for i in range(2, N):
- if flag[i] == 0: prime.append(i)
- return prime
- print(get_prime())
复制代码 快速幂模板
- mod = 10**9+7 # 带mod的pow有快速幂功能
- print(pow(2, 10, mod)) # 1024
复制代码- def ksm(x, a): # return x**a
- res = 1
- while a:
- if a&1:
- res *= x
- a >>= 1
- x *= x
- return res
- print(ksm(2, 10)) # 1024
复制代码 KMP算法
- N = 1000005
- Next = [0] * N
- def getNext(p): # 求前缀数组
- for i in range(1, len(p)):
- j = Next[i]
- while j > 0 and p[i] != p[j]:
- j = Next[j]
- if p[i] == p[j]: Next[i + 1] = j + 1
- else: Next[i] = 0
- def kmp(s, p): # KMP
- j = 0
- ans = 0
- for i in range(0, len(s)):
- while j > 0 and s[i] != p[j]:
- j = Next[j]
- if s[i] == p[j]:
- j += 1
- ans = max(ans, j)
- if j == len(p): return ans
- return ans
- s = input()
- p = input()
- getNext(p)
- print(kmp(s, p))
复制代码 字符串hash
- n, m = map(int, input().split())
- a = [0] + list(input())
- p = 131 # 固定写法防止出现歧义
- mod = 10**9 + 7
- h = [0] * (n + 1)
- for i in range(1, n + 1):
- h[i] = (h[i-1] * p + ord(a[i])) % mod
- def query(l, r):
- return (h[r] - h[l-1] * pow(p, (r-l+1), mod)) % mod
- for _ in range(m):
- l1, r1, l2, r2 = map(int, input().split())
- if query(l1, r1) == query(l2, r2):
- print('Yes')
- else: print('No')
复制代码 矩阵乘法
- def mutiply(A, B):
- n, m = len(A), len(A[0]) # n行m列
- _m, k = len(B), len(B[0]) # m行k列
- C = [[0] * (k) for i in range(n)]
- for i in range(n):
- for j in range(k):
- for d in range(m):
- C[i][j] += (A[i][d] * B[d][j]) % mod
- return C # n行k列
复制代码 gcd与lcm
- from math import gcd
- def lcm(a, b):
- return a * b // gcd(a, b)
- print(gcd(4, 16)) # 4
- print(lcm(4, 16)) # 16
复制代码 唯一分解定理
一个大于1的数N要么为质数,要么可以分解为有限个质数的乘积。
- def f(n):
- factor = []
- for i in range(2, n+1):
- while n % i == 0:
- n //= i
- factor.append(i)
- if n == 1:
- break
- return factor
- print(f(16))
复制代码 结论:因子个数为其每个分解的质数的出现次数+1再相乘
求逆元
- mod = 10**9 + 7 # mod必须为奇数
- def inv(x):
- return pow(x, mod-2, mod)
复制代码 裴蜀定理
a, b为不全为0的整数,则存在x, y满足:ax + by = gcd(a, b)
并查集
- def find(x):
- if x == p[x]: return x
- p[x] = find(p[x]) # 压缩路径
- return p[x]
-
- def merge(x, y):
- xRoot = find(x)
- yRoot = find(y)
- p[xRoot] = yRoot
- def query(x, y):
- return find(x) == find(y)
复制代码 树状数组
- N = 10**9
- tree = [0] * (N)
- def lowbit(x):
- return x & (-x)
- def update(x, d):
- while x <= N:
- tree[x] += d
- x += lowbit(x)
-
- def query(x):
- ans = 0
- while x:
- ans += tree[x]
- x -= lowbit(x)
- return ans
复制代码 Floyd算法
- n, m = map(int, input().split())
- dp = [[0x3f3f3f3f] * (n + 1) for _ in range(n + 1)]
- for _ in range(m):
- x, y, z = map(int, input().split())
- dp[x][y] = dp[y][x] = min(dp[x][y], z)
- for k in range(1, n + 1):
- for i in range(1, n + 1):
- for j in range(1, n + 1):
- dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])
复制代码 Dijkstra算法
- from queue import PriorityQueue
- import sys
- sys.input = sys.stdin.readline
- n, m = map(int, input().split())
- inf = 1<<64
- g = [[] for _ in range(n + 1)]
- for _ in range(m):
- u, v, w = map(int, input().split())
- g[u].append([v, w])
-
- def dijkstra(s):
- global r
- pq = PriorityQueue() # pq[0]表示下一个要走的最优路
- vis = [0] * (n + 1) # 表示某点是否被标记为最优
- r = [inf] * (n + 1) # 存的是起点到i的最短路
- r[s] = 0 # 起点到起点的距离为0
- pq.put([r[s], s]) # 把起点放入优先队列
- while pq.qsize() > 0:
- now = pq.get()
- if vis[now[1]]: continue
- vis[now[1]] = 1
- for i in g[now[1]]:
- v, w = i[0], i[1]
- if vis[v]: continue
- r[v] = min(r[v], r[now[1]] + w)
- pq.put([r[v], v])
- dijkstra(1)
- for i in range(1, n + 1):
- if r[i] >= inf: print(-1, end = ' ')
- else: print(r[i], end = ' ')
复制代码 线段树
单点修改、区间查询
- def build(id, l, r):
- if l == r:
- tree[id] = a[l]
- return
- mid = (l + r) // 2
- build(id * 2, l, mid)
- build(id * 2 + 1, mid + 1, r)
- tree[id] = tree[id * 2] + tree[id * 2 + 1]
-
- def update(pos, v, id, l, r):
- if l == r:
- tree[id] += v
- return
- mid = (l + r) // 2
- if pos <= mid: update(pos, v, id * 2, l, mid)
- else: update(pos, v, id * 2 + 1, mid + 1, r)
- tree[id] = tree[id * 2] + tree[id * 2 + 1]
- def query(L, R, id, l, r):
- if L > r or R < l: return 0
- if L <= l and r <= R: return tree[id]
- mid = (l + r) // 2
- return query(L, R, id * 2, l, mid) + query(L, R, id * 2 + 1, mid + 1, r)
-
- n = int(input())
- a = [0] + list(map(int, input().split()))
- tree = [0] * (4 * n)
- build(1, 1, n)
- for _ in range(int(input())):
- op, x, y = map(int, input().split())
- if op == 1:
- update(x, y, 1, 1, n)
- else:
- print(query(x, y, 1, 1, n))
复制代码 区间修改、区间查询
- def build(id, l, r):
- if l == r:
- tree[id] = a[l]
- return
- mid = (l + r) // 2
- build(id * 2, l, mid)
- build(id * 2 + 1, mid + 1, r)
- tree[id] = tree[id * 2] + tree[id * 2 + 1]
-
- def to_down(id, sl, sr):
- tag[id * 2] += tag[id]
- tag[id * 2 + 1] += tag[id]
- tree[id * 2] += tag[id] * sl
- tree[id * 2 + 1] += tag[id] * sr
- tag[id] = 0
-
- def update(L, R, v, id, l, r):
- if R < l or L > r: return
- if L <= l and r <= R:
- tag[id] += v
- tree[id] += v * (r - l + 1)
- return
- mid = (l + r) // 2
- to_down(id, mid - l + 1, r - mid)
- update(L, R, v, id * 2, l, mid)
- update(L, R, v, id * 2 + 1, mid + 1, r)
- tree[id] = tree[id * 2] + tree[id * 2 + 1]
-
- def query(L, R, id, l, r):
- if R < l or L > r: return 0
- if L <= l and r <= R: return tree[id]
- mid = (l + r) // 2
- to_down(id, mid - l + 1, r - mid)
- return query(L, R, id * 2, l, mid) + query(L, R, id * 2 + 1, mid + 1, r)
-
- n, q = map(int, input().split())
- a = [0] + list(map(int, input().split()))
- tag = [0] * (n<<2)
- tree = [0] * (n << 2)
- build(1, 1, n) # 建树
- for i in range(q):
- op = list(map(int, input().split()))
- if op[0] == 1:
- x, y, z = op[1:]
- update(x, y, z, 1, 1, n)
- else:
- x, y = op[1:]
- print(query(x, y, 1, 1, n))
复制代码 区间最大值
- def bulid(id, l, r):
- if l == r:
- tree[id] = a[l]
- return
- mid = (l + r) // 2
- bulid(id * 2, l, mid)
- bulid(id * 2 + 1, mid + 1, r)
- tree[id] = max(tree[id * 2], tree[id * 2 + 1])
-
- def query(L, R, id, l, r):
- if R < l or L > r: return -0x3f3f3f3f
- if L <= l and r <= R: return tree[id]
- mid = (l + r) // 2
- return max(query(L, R, id * 2, l, mid), query(L, R, id * 2 + 1, mid + 1, r))
- n, q = map(int, input().split())
- a = [0] + list(map(int, input().split()))
- tree = [0] * (n<<2)
- bulid(1, 1, n)
- for _ in range(q):
- x, y = map(int, input().split())
- print(query(x, y, 1, 1, n))
复制代码 LCA最近公共祖先
- import sys
- sys.setrecursionlimit(10000)
- input = sys.stdin.readline
- def dfs(u, fa):
- # 预处理
- deep[u] = deep[fa] + 1
- p[u][0] = fa
- for i in range(1, 21):
- p[u][i] = p[p[u][i - 1]][i - 1]
- for v in G[u]:
- if v == fa: continue
- dfs(v, u)
- def lca(x, y):
- if deep[x] < deep[y]:
- x, y = y, x
- for i in range(20, -1, -1):
- if deep[p[x][i]] >= deep[y]:
- x = p[x][i]
- if x == y:
- return x
- for i in range(20, -1, -1):
- if p[x][i] != p[y][i]:
- x, y = p[x][i], p[y][i]
- return p[x][0]
- n = int(input())
- G = [[] for i in range(n + 1)]
- deep = [0] * (n + 1) # deep[u]表示节点u的深度
- p = [[0] * 21 for i in range(n + 1)] # p[u][i]表示节点u往上走2^i到达的节点
- for _ in range(n - 1):
- u, v = map(int, input().split())
- G[u].append(v)
- G[v].append(u)
- dfs(1, 0)
- Q = int(input())
- for _ in range(Q):
- x, y = map(int, input().split())
- print(lca(x, y))
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |