【蓝桥杯】Python 模版

1 字符串

1.1 字符串哈希

MOD = int(1e9+7)
p = 13331
n = len(s) # 文本串s,长度为n
h = [0] * (n + 5)
for i in range(1, n + 1):
    h[i] = h[i-1] * p + ord(s[i-1]) - ord('A')
    h[i] %= MOD
### 区间和
P = (p ** m) % MOD # 匹配串t的长度为m
(h[r] - h[l-1] * P % MOD + MOD) % MOD

1.2 KMP

n, m = len(s), len(t) # 文本串s和模式串t
ne = [0] * (n + m + 5)
ans, j = 0, 0
cur = t + '#' + s
for i in range(1, n + m + 1):
    while j > 0 and cur[i] != cur[j]:
        j = ne[j-1] # 回退
    if cur[i] == cur[j]:
        j += 1 
    ne[i] = j
    if ne[i] == m and i > m:
        ans += 1

1.3 字典树

# 以01字典树为例
tr = [[0, 0] for _ in range(5 * int(2e5+10))]
cnt = [0] * (5 * int(2e5+10))
ind = 0

def insert(x): # 插入节点
    global ind
    p = 0
    for i in range(20, -1, -1):
        j = x >> i & 1
        if not tr[p][j]:
            ind += 1
            tr[p][j] = ind
        p = tr[p][j]
    cnt[p] += 1 # 记录字符串x出现的次数

def find(x):  # 查找字符串
    p = 0
    for i in x:
        c = ord(i) - ord("a")
        if not tr[p][c]:
            return False
        p = tr[p][c]
    return cnt[p]        

def query_max(x): # 求异或极大值
    res, p = 0, 0
    for i in range(20, -1, -1):
        j = x >> i & 1
        if tr[p][not j]: # 异或运算性质
            res += 1 << i
            p = tr[p][not j]
        else:
            p = tr[p][j]
    return res

def query_min(x): # 求异或极小值
    res, p = 0, 0
    for i in range(20, -1, -1):
        j = x >> i & 1
        if tr[p][j]:
            p = tr[p][j]
        else:
            res += 1 << i
            p = tr[p][not j]
    return res

2 数学

2.1 快速幂

def qpow(a, b):
    res = 1
    while b:
        if b & 1:
            res = res * a % MOD
        a = a * a % MOD
        b >>= 1
    return res % MOD

2.2 数论分块

在这里插入图片描述

2.3 线性筛求欧拉函数和约数个数

phi[1] = 1
d[1] = 1
for i in range(2, n + 1):
    if not vis[i]:
        phi[i] = i - 1 # i的欧拉函数值
        d[i] = 2 # i的约数个数
        num[i] = 1 # i的最小质因子出现次数
        prime.append(i)
    for pri in prime:
        if pri * i > n:
            break
        vis[i * pri] = pri
        if i % pri == 0:
            phi[i * pri] = phi[i] * pri
            num[i * pri] = num[i] + 1
            d[i * pri] = d[i] // num[i * pri] * (num[i * pri] + 1)
            break
        phi[i * pri] = phi[i] * phi[pri]
        num[i * pri] = 1
        d[i * pri] = d[i] * 2

2.4 欧拉定理及其扩展

在这里插入图片描述在这里插入图片描述
t/528c150d1c16482fad221aa75c9ae345.png)

2.5 线性求逆元

inv[1] = 1
for i in range(2, n + 1):
    inv[i] = (p - p // i) * inv[p % i] % p
# 下面是求阶乘逆元
inv[n+1] = qpow(fac[n+1], mod-2)
for i in range(n, -1, -1): 
    inv[i] = inv[i+1] * (i + 1) % mod

2.6 常见数列求和公式

等差数列
在这里插入图片描述
等比数列
在这里插入图片描述
平方数求和
在这里插入图片描述
立方数求和
在这里插入图片描述
递增数列求和(1+3+6+10+15……)
在这里插入图片描述

3 图论

3.1 树链剖分求LCA

def dfs1(x, fa):
    dep[x] = dep[fa] + 1
    siz[x] = 1
    f[x] = fa
    for y in G[x]:
        if y == fa:
            continue
        dfs1(y, x)
        siz[x] += siz[y]
        if not son[x] or siz[son[x]] < siz[y]:
            son[x] = y

def dfs2(x, t):
    top[x] = t
    if not son[x]:
        return 
    dfs2(son[x], t)
    for y in G[x]:
        if y == f[x] or y == son[x]:
            continue
        dfs2(y, y)

def LCA(x, y):
    while top[x] != top[y]:
        if dep[top[x]] < dep[top[y]]:
            x, y = y, x
        x = f[top[x]]
    return x if dep[x] < dep[y] else y

4 动态规划

4.1 背包(c++模板)

V:总重 w[]:各物品重量 c[]:各物品价值 

0/1背包 
for(int i=1;i<=n;i++) 
	for(int j=V;j>=w[i];j--) 
		f[j]=max(f[j],f[j-w[i]]+c[i]);

完全背包 
for(int i=1;i<=n;i++) 
	for(int j=w[i];j<=V;j++) 
		f[j]=max(f[j],f[j-w[i]]+c[i]);

p[]:各物品的数量
 
多重背包O(nmlogp)
for(int i=1;i<=n;i++)
{
	int num=min(p[i],V/w[i]);
	for(int k=1;num>0;k<<=1)
	{
		if(k>num) k=num;
		num-=k;
		for(int j=V;j>=k*w[i];j--)
			f[j]=max(f[j],f[j-k*w[i]]+k*c[i]);
	}		
}

T:总时间 t[]:各个物品的时间 

二维费用背包
for(int i=1;i<=n;i++) 
	for(int j=V;j>=w[i];j--) 
		for(int k=T;k>=t[i];k--) 
			f[j][k]=max(f[j][k],f[j-w[i]][k-t[i]]+1);

lim:总组数 num[]:各组里物品的数量 g[i][k]:第i组第k个物品的下标 
 
分组背包
for(int i=1;i<=lim;i++)
	for(int j=V;j>=0;j--)
		for(int k=1;k<=num[i];k++)
			if(j>=w[g[i][k]])
				f[j]=max(f[j],f[j-w[g[i][k]]]+c[g[i][k]]);

4.2 数位dp

def dfs(i, cnt, limit):
    if cnt > k: return 0
    if i == len(s): return int(cnt == k)
    if (i, cnt, limit) in hashmap:  # 记忆化处理
        return hashmap[(i, cnt, limit)]
    ans = 0
    up = int(s[i]) if limit else 1
    for d in range(up+1): 
       ans += dfs(i+1, cnt + int(d == 1), limit and up == d)
    hashmap[(i, cnt, limit)] = ans
    return ans
dfs(0, 0, True)

5 数据结构

5.1 树状数组

def lowbit(x):
    return x & (-x)

def modify(x, k):
    while x <= n:
        tr[x] ^= k
        x += lowbit(x)

def query(x):
    res = 0
    while x:
        res ^= tr[x]
        x -= lowbit(x)
    return res

5.2 线段树(c++模板)

inline void pushup(ll p) { ans[p]=ans[lch(p)]+ans[rch(p)]; }
inline void build(ll l,ll r,ll p)
{//递归建树 
	if(l==r) { ans[p]=a[l]; return ; }
	ll mid=(l+r)>>1;
	build(l,mid,lch(p));
	build(mid+1,r,rch(p));
	pushup(p);//从叶子节点向上统计信息 
}
inline void f(ll l,ll r,ll p,ll k)
{//f函数用来打懒惰标记+更新区间信息 
	tag[p]+=k;
	ans[p]+=k*(r-l+1);
}
inline void pushdown(ll l,ll r,ll p)
{
	ll mid=(l+r)>>1;
	f(l,mid,lch(p),tag[p]);
	f(mid+1,r,rch(p),tag[p]);
	tag[p]=0;//当懒惰标记向下传递后,父节点得删除标记
}
inline void update(ll l,ll r,ll nl,ll nr,ll p,ll k)
{
	if(nl<=l&&r<=nr)
	{//如果当前区间包含于更新区间,则直接更新当前区间信息
		tag[p]+=k;
		ans[p]+=k*(r-l+1);
		return ;
	}
	pushdown(l,r,p);
	ll mid=(l+r)>>1;
	if(nl<=mid) update(l,mid,nl,nr,lch(p),k);
	//如果更新区间和当前区间的左半部分有交集,则向下更新
	if(nr>mid) update(mid+1,r,nl,nr,rch(p),k);
	//如果右半部分有交集 
	pushup(p);//对更新区间内的元素全部更新完后,再向上统计信息 
}
inline ll query(ll l,ll r,ll ql,ll qr,ll p)
{
	ll res=0;
	if(ql<=l&&r<=qr) return ans[p];
	//如果当前区间包含于查询区间,则直接返回答案
	ll mid=(l+r)>>1;
	pushdown(l,r,p);
	if(ql<=mid) res+=query(l,mid,ql,qr,lch(p));
	if(qr>mid) res+=query(mid+1,r,ql,qr,rch(p));
	return res;
}

6 算法基础和常用函数

6.1 浮点数二分

l, r = 0, float('inf')
while r - l > 1e-8: # 保留位数再右移三个小数点
    mid = (l + r) / 2
    if check():
        l = mid
    else:
        r = mid
return l

6.2 常用函数

# 加深递归深度
import sys
sys.setrecursionlimit(int(1e6))
# 记忆化
from functools import lru_cache
@lru_cache(maxsize=None)
# 二分查找
from bisect import bisect_left, bisect_right
bisect_left # 大于等于查找元素的下标
bisect_right # 大于查找元素的下标
# 二进制转化
bin(x)[2:]
# 优先队列
from queue import PriorityQueue
# 双端队列、栈
from collections import deque
# 计数器和好使的字典
from collections import Counter, defaultdict
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值