算法模板

算法模板整理

高精度运算

高精度加法

1
2
3
4
5
6
7
8
9
10
11
12
13
vector<int> add(vector<int> &a, vector<int> &b) {
if(a.size() < b.size()) return add(b, a);
int t = 0;
vector<int> c;
for(int i = 0; i < a.size(); i++) {
t += a[i];
if(i < b.size()) t += b[i];
c.push_back(t % 10);
t /= 10;
}
if(t) c.push_back(t);
return c;
}

作用:实现两个大整数(用vector存储,低位在前)的加法运算


高精度减法

1
2
3
4
5
6
7
8
9
10
11
12
vector<int> sub(vector<int> &a, vector<int> &b) {
int t = 0;
vector<int> c;
for(int i = 0; i < a.size(); i++) {
t = a[i] - t;
if(i < b.size()) t -= b[i];
c.push_back((t + 10) % 10);
t = t < 0 ? 1 : 0;
}
while(c.size() > 1 && c.back() == 0) c.pop_back();
return c;
}

作用:实现两个大整数(用vector存储,低位在前)的减法运算。


数论

欧拉筛法

1
2
3
4
5
6
7
8
9
10
11
void euler(int n) {
vector<int> prime;
vis[0] = vis[1] = true;
for(int i = 2; i <= n; i++) {
if(!vis[i]) prime.push_back(i);
for(int j = 0; j < prime.size() && i * prime[j] <= n; j++) {
vis[i * prime[j]] = true;
if(i % prime[j] == 0) break;
}
}
}

作用:使用欧拉筛法(线性筛)求出1到n之间的所有质数,并标记合数。


快速幂

1
2
3
4
5
6
7
8
9
int qmi(int a, int b, int p) {
int res = 1;
while(b) {
if(b & 1) res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}

作用:快速计算a的b次方模p的结果。


逆元

1
2
3
int inv(int x, int p) {
return qmi(x, p - 2, p);
}

作用:利用费马小定理计算x在模p意义下的逆元(p必须是质数)


最大公约数 最小公倍数

1
2
3
4
5
6
7
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}

int lcm(int a, int b) {
return a / gcd(a, b) * b;
}

图论

Dijkstra算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
typedef pair<int, int> PII;
priority_queue<PII, vector<PII>, greater<PII>> pq;

vector<int> dijkstra(int n, vector<vector<int>>& edges, int start) {
vector<vector<PII>> adj(n);
for (auto& edge : edges) {
int u = edge[0], v = edge[1], w = edge[2];
adj[u].emplace_back(v, w);
adj[v].emplace_back(u, w);
}
vector<int> dist(n, INT_MAX);
dist[start] = 0;

priority_queue<PII, vector<PII>, greater<PII>> pq;
pq.emplace(0, start);

while (!pq.empty()) {
auto [d, u] = pq.top();
pq.pop();
if (d > dist[u])continue;
for (auto& [v, weight] : adj[u]) {
int new_dist = d + weight;
if (new_dist < dist[v]) {
dist[v] = new_dist;
pq.emplace(new_dist, v);
}
}
}
return dist;
}

作用:使用优先队列优化的Dijkstra算法求解单源最短路径问题(适用于非负权图)。

链式前向星

1
2
3
4
5
6
7
8
9
10
11
struct node {
int next, to, w;
} e[100000];
int head[1000], cnt = 0;

void add_edge(int u, int v, int w) {
e[cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt++;
}

作用:使用链式前向星存储图结构,适用于稀疏图


单调栈与单调队列

单调栈

1
2
3
4
5
6
7
8
9
10
11
12
stack<int> s;
int f[N], a[N];

void compare() {
for(int i = n; i >= 1; i--) {
while(!s.empty() && a[s.top()] <= a[i]) {
s.pop();
}
f[i] = s.empty() ? 0 : s.top();
s.push(i);
}
}

作用:使用单调栈找到每个元素右边第一个比它大的元素的位置。


单调队列(滑动窗口)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int que1[N], hh = 0, tt = 0;
int ans1[N];

void sliding_window() {
for(int i = 1; i <= k - 1; i++) {
while(hh < tt && a[que1[tt - 1]] <= a[i]) {
tt--;
}
que1[tt++] = i;
}
for(int l = 1, r = k; l <= n - k + 1; l++, r++) {
while(hh < tt && a[que1[tt - 1]] <= a[r]) {
tt--;
}
que1[tt++] = r;
ans1[l] = a[que1[hh]];
if(que1[hh] == l) {
hh++;
}
}
}

作用:使用单调队列解决滑动窗口最大值问题。


并查集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int father[N];

int find(int x) {
if(x != father[x]) {
father[x] = find(father[x]);
}
return father[x];
}

bool isSameSet(int x, int y) {
return find(x) == find(y);
}

void unionSet(int x, int y) {
father[find(x)] = find(y);
}

作用:实现并查集数据结构,支持查找和合并操作,用于处理不相交集合的合并与查询问题。


搜索算法

BFS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PII q[N];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};

bool check(int a, int b) {
if(a < 1 || a > n || b < 1 || b > m) {
return false;
}
return true;
}

void bfs() {
while(hh <= tt) {
auto t = q[hh++];
for(int i = 0; i < 4; i++) {
int a = t.first + dx[i];
int b = t.second + dy[i];
if(!check(a, b) || dis[a][b] >= 0) continue;
dis[a][b] = dis[t.first][t.second] + 1;
q[++tt] = {a, b};
}
}
}

作用:广度优先搜索算法,用于解决最短路径或连通性问题。


DFS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int d[N], p1, p2;

void dfs(int x, int fa) {
if(d[p1] < d[x]) {
p1 = x;
}
for(auto y : point[x]) {
if(y == fa) continue;
d[y] = d[x] + 1;
dfs(y, x);
}
}

void dfs1(int x, int fa) {
if(d1[p2] < d1[x]) {
p2 = x;
}
for(auto y : point[x]) {
if(y == fa) continue;
d1[y] = d1[x] + 1;
dfs1(y, x);
}
}

作用:使用两次深度优先搜索求解树的直径(树中最长路径)。第一次DFS找到最远点p1,第二次从p1出发找到最远点p2,p1和p2之间的路径即为树的直径。


算法模板
https://siltal.github.io/2025/04/11/算法模板/
Author
Siltal
Posted on
April 11, 2025
Licensed under