Python常用算法模板(蓝桥杯)

写在前面

一些可以直接调用的板子我都在下面给出,主要适用于蓝桥杯的Python选手。一些没有固定模板的写法在本文中不列出,如有重要知识点遗漏,欢迎大家指出。
在这里插入图片描述

快读

import sys
input = sys.stdin.readline

记忆化

from functools import lru_cache
@lru_cache(maxsize=None)
def dfs(a, b):
	pass

日期问题

常用库函数:

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-1][j-1]

print(prex) # [[0, 0, 0, 0], [0, 1, 3, 6], [0, 5, 12, 21], [0, 12, 27, 45]]

差分模板

一维差分:

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 = int(input())
dp = [[0x3f3f3f3f] * (n + 1) for _ in range(n + 1)]
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 = ' ')
  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Keven1Duan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值