C++ 竞赛常用算法模板速查表

C++ 竞赛常用算法模板速查表


复制代码
------彭彭老师

内容涵盖了以下 11 大模块

模块 内容
一、基础工具 快速 I/O、GCD/LCM、快速幂、组合数预处理
二、素数相关 素数判断、埃氏筛、线性筛(欧拉筛)、区间筛
三、排序算法 快速排序(手写)、归并排序(含逆序对)、STL sort
四、二分查找 整数二分(左右边界)、实数二分、二分答案
五、前缀和与差分 一维/二维前缀和、一维/二维差分
六、双指针 对撞指针、快慢指针
七、贪心算法 区间贪心
八、递归与分治 分治思想回顾
九、常用 STL 速查 vector/sort/lower_bound/优先队列/map 等
十、动态规划基础 0/1背包、完全背包、LIS、LCS
十一、数学公式速查 数列求和、排列组合、容斥原理、卡特兰数等

具体如下:


📚 C++ 算法竞赛常用模板速查表

这份速查表涵盖了基础工具、数论、排序、二分、数据结构、动态规划等核心模块,适用于 OI/ACM/ICPC 等算法竞赛复习。

一、基础工具

1. 快速输入输出 (IO 优化)

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    // 关闭 C 和 C++ 标准流的同步,大幅提升 cin/cout 速度
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    int n;
    cin >> n;
    cout << n << endl;
    return 0;
}

2. 最大公约数与最小公倍数

cpp 复制代码
#include <numeric> // C++17 起包含 gcd/lcm
using namespace std;

// 手写 GCD (欧几里得算法)
long long gcd(long long a, long long b) {
    return b == 0 ? a : gcd(b, a % b);
}

// 手写 LCM
long long lcm(long long a, long long b) {
    return a / gcd(a, b) * b; // 先除后乘防止溢出
}

3. 快速幂

计算 ab(modp)a^b \pmod pab(modp),时间复杂度 O(log⁡b)O(\log b)O(logb)。

cpp 复制代码
long long qpow(long long a, long long b, long long p) {
    long long res = 1 % p;
    a %= p;
    while (b) {
        if (b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}

4. 组合数预处理 (杨辉三角)

适用于 n,mn, mn,m 较小(如 n≤5000n \le 5000n≤5000)的情况。

cpp 复制代码
const int MAXN = 5005;
long long C[MAXN][MAXN];

void init_comb() {
    for (int i = 0; i < MAXN; i++) {
        C[i][0] = C[i][i] = 1;
        for (int j = 1; j < i; j++) {
            C[i][j] = (C[i-1][j] + C[i-1][j-1]); // 若需取模在此处 % MOD
        }
    }
}

二、素数相关

1. 素数判断 (试除法)

时间复杂度 O(n)O(\sqrt{n})O(n )。

cpp 复制代码
bool is_prime(int n) {
    if (n < 2) return false;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) return false;
    }
    return true;
}

2. 埃拉托斯特尼筛法 (埃氏筛)

时间复杂度 O(nlog⁡log⁡n)O(n \log \log n)O(nloglogn)。

cpp 复制代码
const int MAXN = 1000005;
bool is_prime[MAXN];

void sieve(int n) {
    fill(is_prime, is_prime + n + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i * i <= n; i++) {
        if (is_prime[i]) {
            for (int j = i * i; j <= n; j += i) {
                is_prime[j] = false;
            }
        }
    }
}

3. 线性筛 (欧拉筛)

时间复杂度 O(n)O(n)O(n),同时可求出最小质因子。

cpp 复制代码
const int MAXN = 1000005;
int primes[MAXN], cnt;
bool is_composite[MAXN];

void linear_sieve(int n) {
    for (int i = 2; i <= n; i++) {
        if (!is_composite[i]) primes[cnt++] = i;
        for (int j = 0; j < cnt && i * primes[j] <= n; j++) {
            is_composite[i * primes[j]] = true;
            if (i % primes[j] == 0) break; // 关键:保证每个合数只被其最小质因子筛掉
        }
    }
}

三、排序算法

1. 快速排序 (手写)

cpp 复制代码
void quick_sort(int q[], int l, int r) {
    if (l >= r) return;
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j) {
        do i++; while (q[i] < x);
        do j--; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j);
    quick_sort(q, j + 1, r);
}

2. 归并排序 (含逆序对统计)

cpp 复制代码
long long merge_sort(int q[], int tmp[], int l, int r) {
    if (l >= r) return 0;
    int mid = l + r >> 1;
    long long res = merge_sort(q, tmp, l, mid) + merge_sort(q, tmp, mid + 1, r);
    
    int i = l, j = mid + 1, k = 0;
    while (i <= mid && j <= r) {
        if (q[i] <= q[j]) tmp[k++] = q[i++];
        else {
            tmp[k++] = q[j++];
            res += mid - i + 1; // 统计逆序对
        }
    }
    while (i <= mid) tmp[k++] = q[i++];
    while (j <= r) tmp[k++] = q[j++];
    for (i = l, k = 0; i <= r; i++, k++) q[i] = tmp[k];
    return res;
}

3. STL Sort

cpp 复制代码
#include <algorithm>
#include <vector>
using namespace std;

vector<int> v = {3, 1, 4, 1, 5};
sort(v.begin(), v.end()); // 升序
sort(v.begin(), v.end(), greater<int>()); // 降序

四、二分查找

1. 整数二分 (查找左边界/第一个 >= x 的位置)

cpp 复制代码
int binary_search_left(int q[], int n, int x) {
    int l = 0, r = n - 1;
    while (l < r) {
        int mid = l + r >> 1;
        if (q[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return (q[l] == x) ? l : -1;
}

2. 实数二分

cpp 复制代码
double binary_search_double(double l, double r) {
    for (int i = 0; i < 100; i++) { // 循环 100 次精度足够
        double mid = (l + r) / 2;
        if (check(mid)) r = mid; // check 是判断条件
        else l = mid;
    }
    return l;
}

五、前缀和与差分

1. 一维前缀和

cpp 复制代码
int s[MAXN]; // s[i] = a[1] + ... + a[i]
// 区间和 [l, r] = s[r] - s[l-1]

2. 二维前缀和

cpp 复制代码
int s[MAXN][MAXN];
// s[i][j] 表示从 (1,1) 到 (i,j) 的矩形和
// 初始化: s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j]
// 查询子矩阵 (x1,y1) 到 (x2,y2):
// sum = s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1]

3. 一维差分

cpp 复制代码
// b[i] = a[i] - a[i-1]
// 给区间 [l, r] 加上 c: b[l] += c, b[r+1] -= c
// 最后对 b 求前缀和还原 a

六、双指针

1. 对撞指针 (Two Pointers)

常用于有序数组中找两数之和。

cpp 复制代码
int i = 0, j = n - 1;
while (i < j) {
    if (a[i] + a[j] == target) { /* found */ break; }
    else if (a[i] + a[j] < target) i++;
    else j--;
}

七、贪心算法

1. 区间调度 (按右端点排序)

cpp 复制代码
struct Interval {
    int l, r;
    bool operator<(const Interval &t) const {
        return r < t.r; // 按右端点升序
    }
};
// 排序后依次选择不重叠的区间

八、递归与分治

1. 分治求最大值

cpp 复制代码
int find_max(int q[], int l, int r) {
    if (l == r) return q[l];
    int mid = l + r >> 1;
    return max(find_max(q, l, mid), find_max(q, mid + 1, r));
}

九、常用 STL 速查
容器/函数 用法 复杂度
vector<int> v v.push_back(x), v.size() O(1)O(1)O(1) 均摊
sort(v.begin(), v.end()) 排序 O(nlog⁡n)O(n \log n)O(nlogn)
lower_bound 找第一个 ≥x\ge x≥x 的位置 O(log⁡n)O(\log n)O(logn)
priority_queue<int> 大根堆 插入/删除 O(log⁡n)O(\log n)O(logn)
map<int, int> 红黑树实现 插入/查找 O(log⁡n)O(\log n)O(logn)
unordered_map 哈希表实现 插入/查找 O(1)O(1)O(1) 平均

十、动态规划基础

1. 0/1 背包

cpp 复制代码
int dp[MAXW]; // dp[j] 表示容量为 j 的最大价值
for (int i = 0; i < n; i++) {
    for (int j = W; j >= w[i]; j--) { // 倒序遍历
        dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
    }
}

2. 完全背包

cpp 复制代码
for (int i = 0; i < n; i++) {
    for (int j = w[i]; j <= W; j++) { // 正序遍历
        dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
    }
}

3. 最长上升子序列 (LIS) - O(n2)O(n^2)O(n2)

cpp 复制代码
int dp[MAXN]; // dp[i] 表示以 a[i] 结尾的 LIS 长度
for (int i = 0; i < n; i++) {
    dp[i] = 1;
    for (int j = 0; j < i; j++) {
        if (a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1);
    }
}

十一、数学公式速查

1. 等差数列求和

Sn=n(a1+an)2S_n = \frac{n(a_1 + a_n)}{2}Sn=2n(a1+an)

2. 等比数列求和

Sn=a11−qn1−q(q≠1)S_n = a_1 \frac{1-q^n}{1-q} \quad (q \neq 1)Sn=a11−q1−qn(q=1)

3. 排列组合

  • 排列:Anm=n!(n−m)!A_n^m = \frac{n!}{(n-m)!}Anm=(n−m)!n!
  • 组合:Cnm=n!m!(n−m)!C_n^m = \frac{n!}{m!(n-m)!}Cnm=m!(n−m)!n!
  • 性质:Cnm=Cnn−mC_n^m = C_n^{n-m}Cnm=Cnn−m, Cnm=Cn−1m+Cn−1m−1C_n^m = C_{n-1}^m + C_{n-1}^{m-1}Cnm=Cn−1m+Cn−1m−1

4. 容斥原理

∣A∪B∣=∣A∣+∣B∣−∣A∩B∣|A \cup B| = |A| + |B| - |A \cap B|∣A∪B∣=∣A∣+∣B∣−∣A∩B∣

5. 卡特兰数

Cn=1n+1C2nnC_n = \frac{1}{n+1} C_{2n}^nCn=n+11C2nn

应用:出栈序列数、二叉树形态数等。


相关推荐
高洁011 小时前
工信部教考中心证书
人工智能·深度学习·算法·机器学习·知识图谱
离陌在学C#1 小时前
C# 泛型:从基础到高级应用
开发语言·c#
ly76891 小时前
Java 设计模式详解:从原则到 23 种经典模式
java·开发语言·设计模式
SomeB1oody1 小时前
【RustyML入门】2.13. 孤立森林
开发语言·后端·机器学习·rust·教程
我变成萤火虫1 小时前
河南萌新联赛2026第(三)场:郑州轻工业大学
数据结构·c++·算法·贪心算法·stl·深度优先·哈希算法
Dr.kangder1 小时前
嵌入式面试总结(十九)——内存泄露
单片机·算法·面试·职场和发展·架构·硬件架构
萧瑟余晖1 小时前
Java深入解析篇三十之Java日志框架
java·开发语言
Herbert_hwt2 小时前
【C语言基础】常量、选择结构与运算符全解析
c语言·开发语言·算法
buhuizhiyuci2 小时前
【Linux 篇】数字世界的水流蓄水池 —— IO 缓冲区机制深度实战解析
linux·运维·服务器·c++