基础算法

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

  1. 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. 二项式反演

有两个公式

  1. 记f(i) 为 恰好为i个的方案数 g(i) 为 $\binom{n}{k}$
from math import comb
# comb(n,k) : C(n,k)

2. lcm和gcd

  1. 我们对一个数进行质因数分解,我们可以知道说有 $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