基础算法
1. 二分
import bisect
import random
## 如果不加哨兵的情况下
a = [i for i in range(100)]
x = random.randint(1,100)
id1 = bisect.bisect_left(a,x) ## 可以看作返回的是 第一个 >= x的下标,也可以看作是返回的是 < x 的a数组中的个数
id2 = bisect.bisect_right(a,x) ## 同理变成 < x和 <= x 的a数组中的个数
// 同理在cpp中
#include <algorithm>
val = lower_bound(a,x) - a.begin() // a可以是一个vector或者是一个数组,但是返回的是迭代器,所以要minus a.begin()
2. binary lifting
- abc438e
DS
1. BIT
# c[i] : [i - lowbit(i) + 1,i] 这段区间的sum
# 下面的是单点修改以及区间求和的template,区间修改和单点求和就是差分版
# 其中kth函数是找出最小的 >= k的下标
class BIT:
def __init__(self,n):
self.n = n
self.c = [0] * (n + 1)
def insert(self,idx,val):
while idx <= self.n:
self.c[idx] += val
idx += lowbit(idx)
def sum(self,l,r):
s = 0
while l:
s -= self.c[l]
l -= lowbit(l)
while r:
s += self.c[r]
r += lowbit(r)
return s
def kth(self,k):
step = 1 << (self.n.bit_length() - 1)
idx = 0
while idx <= self.n and self.c[idx] < k:
nxt = idx + step
k -= self.c[nxt]
step >>= 1
2. 对顶堆
常见的用途是用来取中位数 -abc458d
hp1,hp2 = [],[]
def update():
global hp1,hp2
if len(hp1) > len(hp2) + 1:
heapq.heappush(hp2,-heapq.heappop(hp1))
elif len(hp1) < len(hp2):
heapq.heappush(hp1,-heapq.heappop(hp2))
def add(x):
global hp1,hp2
if not hp1 or -x >= hp1[0]:
heapq.heappush(hp1,-x)
else:
heapq.heappush(hp2,x)
update()
MATH
1. 二项式反演
有两个公式
- 记f(i) 为 恰好为i个的方案数 g(i) 为 $\binom{n}{k}$
from math import comb
# comb(n,k) : C(n,k)
2. lcm和gcd
- 我们对一个数进行质因数分解,我们可以知道说有
$X = p_1^{c_1} * p_2^{c_2} * ... * p_n^{c_n}$
那么我们记a为gcd,b为lcm
我们有以下的式子 : $$ a = \prod_{i=1}^{i=n} p_i^{min(c_1,c_2,...,c_n)}\\\\ b = \prod_{i=1}^{i=n} p_i^{max(c_1,c_2,...,c_n)} $$
3. 调和级数
- abc452e