🏆 信竞新手速查板

复制即用的 C++ 竞赛模板 · 数据类型范围 · STL 速查 · 避坑清单

① 文件头模板(点按钮一键复制)

万能头版(比赛最常用)推荐

一个 #include <bits/stdc++.h> 包揽所有头文件,不用背。大多数 OJ(洛谷、CSP 认可的平台)都支持。

#include <bits/stdc++.h>
using namespace std;

int main() {

    return 0;
}

② 常用数据类型定义范围

2.1 整数类型

类型关键字字节范围大约能存多大
短整型short2−32768 ~ 32767±3 万
整型int4−2147483648 ~ 2147483647±21 亿(≈2.1×10⁹)
长整型long long8−9223372036854775808 ~ 9223372036854775807±9.2×10¹⁸
无符号整型unsigned int40 ~ 42949672950 ~ 42 亿
无符号长整型unsigned long long80 ~ 184467440737095516150 ~ 1.8×10¹⁹

📌 范围公式:n 字节有符号范围是 −2^(8n−1) ~ 2^(8n−1)−1。

2.2 浮点 / 字符 / 布尔

类型关键字字节有效精度 / 说明
单精度浮点float4约 6~7 位有效数字(少用,易精度丢)
双精度浮点double8约 15~16 位有效数字(浮点题首选)
长双精度long double12/16约 18~19 位有效数字
字符char1−128 ~ 127;一个字母/数字占 1 字节(ASCII)
布尔bool1只有 true(1)和 false(0)

2.3 竞赛常用大数常量

常量值建议写法 / 用途
int 最大值2147483647INT_MAX(求最小值时当"哨兵"初值)
int 最小值−2147483648INT_MIN(求最大值时当哨兵初值)
long long 最大值≈9.22×10¹⁸LLONG_MAX
"无穷大"—const int INF = 0x3f3f3f3f;(≈10.6 亿,图论常用)
圆周率3.14159265358979…const double PI = acos(-1.0);

③ 取值范围记忆口诀 & 选题技巧

3.1 一眼判断用 int 还是 long long

题目数据范围写着结论
n ≤ 10⁴(1 万)int 稳够,n² = 10⁸ 也可跑(勉强)
n ≤ 10⁵(10 万)int 够;但 n² = 10¹⁰ 会超时,想 O(n log n)
n ≤ 10⁹(10 亿)数值超 int 范围的边缘,乘法/求和必炸 → 用 long long
数值到 10¹⁰ ~ 10¹⁸必须 long long
数值超过 10¹⁸long long 也装不下 → 高精度(用字符串/数组模拟)
⚠️ 两个 int 相乘(如 10⁵ × 10⁵ = 10¹⁰)会先在 int 里溢出再赋值,结果就是错的!要写成 (long long)a * b,先转型再乘。

3.2 好记的口诀

  • 🔢 int 21 亿:约 2.1×10⁹,记作「十位数」——只要数字不超过 10 位(9,999,999,999 以内)int 就危险了,10 位数一律上 long long。
  • 📏 long long 9×10¹⁸:19 位数字封顶,记「十九个 9」。
  • ⏱️ 复杂度表(1 秒约跑 10⁸~10⁹ 次简单运算):
    n 的规模能接受的复杂度
    n ≤ 20O(2ⁿ) 搜索 / 枚举子集
    n ≤ 500O(n³)
    n ≤ 5000O(n²)
    n ≤ 10⁵ ~ 10⁶O(n log n) 或 O(n)
    n ≤ 10⁸只能 O(log n)、O(√n)、O(1)

④ STL 常用速查

4.1 容器一览

容器是什么常用操作复杂度
vector<int> v;动态数组v.push_back(x) / v.size() / v[i]尾部插入 O(1)
set<int> s;自动排序+去重s.insert(x) / s.count(x) / s.erase(x)O(log n)
map<string,int> m;键值对(按键排序)m[key] = val / m.count(key)O(log n)
priority_queue<int> q;大根堆q.push(x) / q.top() / q.pop()O(log n)
queue<int> q;队列(BFS 用)q.push(x) / q.front() / q.pop()O(1)
stack<int> st;栈(DFS/括号匹配)st.push(x) / st.top() / st.pop()O(1)
pair<int,int> p;成对数据p.first / p.second / make_pair(a,b)—

📌 小根堆写法:priority_queue<int, vector<int>, greater<int>> q;

4.2 algorithm 常用函数

函数作用示例
sort排序(默认升序)sort(v.begin(), v.end());
max / min取大 / 取小max(a, b)
swap交换swap(a, b);
reverse翻转reverse(v.begin(), v.end());
lower_bound第一个 ≥ x 的位置(需已排序)lower_bound(v.begin(), v.end(), x) - v.begin()
upper_bound第一个 > x 的位置(需已排序)upper_bound(v.begin(), v.end(), x) - v.begin()
__gcd最大公约数__gcd(a, b)
abs绝对值abs(a)
fill数组整体赋值fill(dp, dp + n, 0);

4.3 降序排序 + 自定义排序

// 降序排序
sort(v.begin(), v.end(), greater<int>());

// 按结构体某个成员排序(例如按分数从高到低)
struct Stu { int score; string name; };
sort(stu, stu + n, [](const Stu &a, const Stu &b) {
    return a.score > b.score;   // a 排在 b 前面返回 true
});

⑤ 常用算法小模板

5.1 二分查找(手写版)

int lo = 0, hi = n - 1;
while (lo <= hi) {
    int mid = lo + (hi - lo) / 2;
    if (a[mid] == target) { /* 找到 */ break; }
    else if (a[mid] < target) lo = mid + 1;
    else hi = mid - 1;
}

5.2 快速幂(a^b % p)

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

5.3 判断质数

bool isPrime(int n) {
    if (n < 2) return false;
    for (int i = 2; (long long)i * i <= n; i++)
        if (n % i == 0) return false;
    return true;
}

5.4 埃氏筛(1~n 全部质数)

vector<bool> vis(n + 1, false);
vector<int> primes;
for (int i = 2; i <= n; i++) {
    if (!vis[i]) {
        primes.push_back(i);
        for (long long j = (long long)i * i; j <= n; j += i)
            vis[j] = true;
    }
}

5.5 BFS 网格最短路(四方向)

int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
queue<pair<int,int>> q;
q.push({sx, sy});
vis[sx][sy] = true;
while (!q.empty()) {
    auto [x, y] = q.front(); q.pop();
    for (int d = 0; d < 4; d++) {
        int nx = x + dx[d], ny = y + dy[d];
        if (nx >= 0 && nx < n && ny >= 0 && ny < m
            && !vis[nx][ny]) {
            vis[nx][ny] = true;
            dis[nx][ny] = dis[x][y] + 1;
            q.push({nx, ny});
        }
    }
}

5.6 前缀和 & 差分

// 前缀和:求区间 [l, r] 的和
pre[0] = 0;
for (int i = 1; i <= n; i++) pre[i] = pre[i-1] + a[i];
// 区间和 = pre[r] - pre[l-1]

// 差分:区间 [l, r] 整体加 c
d[l] += c; d[r + 1] -= c;
// 最后一遍前缀和还原

⑥ 新手避坑清单

  • 💥 溢出:看到 10⁵ 以上的数相乘/累加,先想 long long。乘法写 (long long)a * b。
  • 📂 文件 IO:CSP/NOIP 上机考试必须写 freopen,文件名和题目完全一致,忘了=0 分。
  • 🔢 数组开小:数组大小 = 题目上限 + 5(防止差分/边界越界),如 a[100005]。
  • 🔁 死循环:while 循环检查循环变量一定会变化;二分的 mid 计算写 lo + (hi - lo) / 2 防溢出。
  • 🧹 多组数据:多测试点的题(如 n 组询问),数组、变量每组都要清零/重置。
  • 🔤 读带空格的整行:用 getline(cin, s),注意它前面如果有 cin >> x 要先 cin.ignore() 吃掉换行。
  • 🖨️ 输出格式:看清题目要求——行末多余空格、大小写、保留小数(printf("%.2f", x))都可能判错。
  • ⏱️ 对拍自查:写完先用样例测,再自己造极端数据(最小值、最大值、全相同、边界)测一遍。
  • 💾 long long 输出:printf 要用 %lld,cout 则直接输出即可。
  • 🧊 变量初始化:全局数组自动清零,局部数组是随机值,必须手动初始化!

🔒 随手记(密码保护)

设置一个随手记密码

首次使用请创建密码。笔记会用 AES-GCM 加密后保存在本机浏览器里,没有密码谁也看不到(包括你自己)。