3303 字
17 分钟
C++ 常用头文件

C++常用头文件#

本节按头文件分组整理算法竞赛常用 API:cmath 负责数学函数,algorithm 负责通用算法(排序、查找、堆),numeric 负责数值算法(累加、GCD、扫描)。三者搭配 STL 容器,覆盖刷题 90% 的场景。

cmath#

<cmath> 是 C 标准数学库的 C++ 包装,所有函数都在 std 命名空间下,参数和返回值多为 double。刷题时最常用的是取整、幂运算、浮点处理三类。

常用函数速览#

函数功能备注
abs(x)整数绝对值实际定义在 <cstdlib>,C++11 起 <cmath> 也支持
fabs(x)浮点绝对值等价于 abs(double)
sqrt(x)平方根pow(x, 0.5) 更快、更准
cbrt(x)立方根C++11 起
pow(x, y)x^y整数次方不要用它,会引入浮点误差
exp(x)e^x
log(x)自然对数底为 e
log10(x)常用对数底为 10
log2(x)底为 2 的对数C++11 起
hypot(x, y)sqrt(x² + y²)防数值溢出专用,见下
max(a, b) / min(a, b)两值最大/最小也可处理 initializer_list(C++11)
fmax(a, b) / fmin(a, b)浮点版 max/min处理 NaN 行为不同

三角函数#

函数功能
sin / cos / tan正弦 / 余弦 / 正切(弧度)
asin / acos / atan反正弦 / 反余弦 / 反正切
sinh / cosh / tanh双曲正弦 / 余弦 / 正切
atan2(y, x)二参数反正切,能区分象限(比 atan(y/x) 安全)

常用常量

常量
M_PI圆周率 π
M_E自然常数 e
M_SQRT2√2

注意M_PI 不是 C++ 标准的一部分,GCC/Clang 默认开启,MSVC 需定义 _USE_MATH_DEFINES 后 include <cmath>。严谨做法是自己定义const double PI = acos(-1.0);

取整函数#

函数功能示例(x = 2.7示例(x = -2.7
ceil(x)向上取整3-2
floor(x)向下取整2-3
round(x)四舍五入(远离 0)3-3
trunc(x)截断小数部分2-2
fmod(x, y)浮点取模(结果符号同 x
#include <cmath>
#include <iostream>
using namespace std;
int main() {
cout << ceil(2.7) << " " << floor(2.7) << " " << round(2.7) << endl; // 3 2 3
cout << ceil(-2.7) << " " << floor(-2.7) << " " << round(-2.7) << endl; // -2 -3 -3
return 0;
}

⚠ 警告负数取整的方向常与直觉相反floor(-2.7) = -3(向更小的整数),刷题务必测试。

幂运算与整数次方#

⚠ 警告pow(2, 10) 看似能算 2^10,但内部用浮点实现,结果可能因精度损失而不准(如 pow(10, 2) = 99.9999...)。整数次方用快速幂(手写)或 1LL << n(仅限 2 的幂)。

// 整数快速幂:a^n mod mod(比赛最常用)
long long qpow(long long a, long long n, long long mod) {
long long res = 1;
a %= mod;
while (n > 0) {
if (n & 1) res = res * a % mod;
a = a * a % mod;
n >>= 1;
}
return res;
}

浮点处理技巧#

1. 浮点比较== 比较浮点几乎一定出错,必须用容差:

#include <cmath>
const double EPS = 1e-9;
bool eq(double a, double b) { return fabs(a - b) < EPS; }
bool lt(double a, double b) { return a < b - EPS; }
bool le(double a, double b) { return a < b + EPS; }

2. 防止 sqrt(x² + y²) 溢出

// 错误:x、y 很大时 x*x 先溢出
double len = sqrt(x * x + y * y);
// 正确:hypot 内部做缩放
double len = hypot(x, y);

3. INF / NaN

double inf = numeric_limits<double>::infinity();
double nan = numeric_limits<double>::quiet_NaN();

关键注意点#

易错点说明
整数次方用 pow浮点精度坑,改用快速幂
三角函数单位是弧度转角度:rad * PI / 180
负数 floor / ceil方向与直觉相反
M_PI非标准常量,MSVC 需宏定义
浮点 ==必带 EPS 容差
sqrt(x*x + y*y)大数时改用 hypot(x, y)

algorithm#

<algorithm> 是 STL 算法层的核心头文件,提供排序、查找、变换、堆等通用算法。所有算法通过迭代器操作容器,与具体容器解耦。

取最值#

函数范围返回值
min(a, b) / max(a, b)两个值较小/较大的值
min({a, b, c}) / max({...})多个值(C++11 initializer_list)同上
min_element(begin, end)区间迭代器,需 * 解引用
max_element(begin, end)区间迭代器,需 * 解引用
minmax(a, b)两个值pair<较小值, 较大值>
minmax_element(begin, end)区间pair<最小迭代器, 最大迭代器>
clamp(v, lo, hi)单值(C++17)钳制到 [lo, hi]
#include <algorithm>
using namespace std;
vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
// 容器里的最大值(迭代器要 * 解引用)
auto it = max_element(v.begin(), v.end());
cout << *it; // 9
cout << it - v.begin(); // 4(下标)
// 三个数
cout << max({1, 5, 3}); // 5
// 钳制
cout << clamp(15, 0, 10); // 10

排序#

函数特点
sort(begin, end)快速排序(实际 introsort),O(n log n),不稳定
stable_sort(begin, end)稳定排序,相等元素保持原顺序
partial_sort(begin, mid, end)排序到 mid取前 k 小 O(n log k)
nth_element(begin, nth, end)nth 位置就位(前 k 小,不保证其余顺序)
is_sorted(begin, end)是否已排序(O(n))
vector<int> v = {3, 1, 4, 1, 5};
sort(v.begin(), v.end()); // 1 1 3 4 5
partial_sort(v.begin(), v.begin() + 2, v.end());// 前 2 小排到头部

注意sortcmp(x, y) 返回 true 表示 x 排前;必须用严格 > / <,不能 >= / <=

查找#

函数前提返回值
find(begin, end, val)第一个等于 val 的迭代器
find_if(begin, end, pred)第一个满足 pred 的迭代器
count(begin, end, val)等于 val 的元素个数
count_if(begin, end, pred)满足 pred 的元素个数
binary_search(begin, end, val)已排序bool:是否存在
lower_bound(begin, end, val)已排序第一个 >= val 的迭代器
upper_bound(begin, end, val)已排序第一个 > val 的迭代器
equal_range(begin, end, val)已排序[lower, upper)pair
vector<int> v = {1, 2, 2, 3, 4};
auto lo = lower_bound(v.begin(), v.end(), 2); // 指向第一个 2
auto hi = upper_bound(v.begin(), v.end(), 2); // 指向 3
cout << hi - lo; // 2(2 出现了 2 次)

修改 / 变换#

函数功能
reverse(begin, end)翻转
rotate(begin, mid, end)旋转(mid 移到开头)
shuffle(begin, end, rng)随机打乱(C++11,需 <random> 引擎)
next_permutation(begin, end)下一个排列,到末尾返回 false
prev_permutation(begin, end)上一个排列
fill(begin, end, val)填充
replace(begin, end, old, new)替换
unique(begin, end)相邻去重(需先 sort
swap(a, b) / iter_swap(it1, it2)交换

注意unique 只删相邻重复,所以通常先 sortunique。返回值是新结尾迭代器:v.erase(it, v.end())

vector<int> v = {1, 2, 2, 3, 2, 4};
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end()); // 1 2 3 4

集合算法(已排序区间)#

输入区间必须有序,结果区间可与输入重叠。

函数含义
merge(a, b, out)归并两个有序区间到 out
set_union(a, b, out)并集
set_intersection(a, b, out)交集
set_difference(a, b, out)差集(在 a 不在 b)
set_symmetric_difference(a, b, out)对称差
includes(a, b)b 是否是 a 的子集

堆(priority_queue 替代品)#

priority_queue 内部用堆,但只暴露受限接口。如需在任意位置操作堆,用 algorithm 提供的 4 个函数。

函数功能
make_heap(begin, end)把区间建成大根堆(默认 less,最大元素在 begin
push_heap(begin, end)假设 end-1 是新元素,上浮调整
pop_heap(begin, end)把堆顶移到 end-1下沉调整
sort_heap(begin, end)堆排序(区间先 make_heap)
is_heap(begin, end)是否是堆
vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
make_heap(v.begin(), v.end()); // 大根堆:9 在 v[0]
pop_heap(v.begin(), v.end()); // 9 移到末尾
cout << v.back(); // 9
v.pop_back(); // 真正删除

注意:默认是大根堆less),想要小根堆传 greater<int>{}make_heap(v.begin(), v.end(), greater<int>());

其他常用#

函数功能
for_each(begin, end, f)对每个元素执行 f(C++17 起可返回)
transform(a, b, out, f)f 应用到元素,写到 out
any_of / all_of / none_of谓词判断(任一/全部/无)
equal(a, b) / equal(a, b, pred)两区间是否相等
lexicographical_compare字典序比较
partition / stable_partition按谓词分两段

numeric#

<numeric> 提供针对数值的算法:累加、内积、扫描、序列生成、最大公约数等。accumulate 是刷题出现频率最高的之一。

累加 / 归约#

函数功能
accumulate(begin, end, init)累加 + 初始值(可自定义二元运算)
accumulate(begin, end, init, op)自定义运算(如 multiplies 求积)
reduce(begin, end, init)类似但无序(C++17,并行友好)
inner_product(a, b, init)两区间内积 + 初始值
transform_reducetransform + reduce 组合(C++17)
#include <numeric>
vector<int> v = {1, 2, 3, 4, 5};
int sum = accumulate(v.begin(), v.end(), 0); // 15
int prod = accumulate(v.begin(), v.end(), 1, multiplies<int>()); // 120
// 字符串拼接(init 给空串)
string s = accumulate(v.begin(), v.end(), string(""),
[](string a, int x) { return a + to_string(x); });
// "12345"

注意accumulate 的初始值是累加的起点(不是数组里的元素),整数累加请写 0LL 避免溢出。

扫描(部分和 / 相邻差)#

函数功能
partial_sum(begin, end, out)前缀和(含当前项)
inclusive_scanC++17,等价 partial_sum
exclusive_scan(begin, end, out, init)前缀和(不含当前项,从 init 开始)
adjacent_difference(begin, end, out)相邻元素差(首元素不变)
vector<int> v = {1, 2, 3, 4, 5};
vector<int> pre(5), diff(5);
partial_sum(v.begin(), v.end(), pre.begin()); // 1 3 6 10 15
adjacent_difference(v.begin(), v.end(), diff.begin());// 1 1 1 1 1

序列生成#

函数功能
iota(begin, end, val)val 开始递增填充:v[i] = val + i
vector<int> v(5);
iota(v.begin(), v.end(), 10); // 10 11 12 13 14

GCD / LCM(C++17)#

函数功能
gcd(a, b)最大公约数(C++17)
lcm(a, b)最小公倍数(C++17)
midpoint(a, b)两数中点(避免 (a+b)/2 溢出,C++20)
cout << gcd(12, 18); // 6
cout << lcm(4, 6); // 12
// 安全的 a+b/2
long long mid = midpoint(1LL, 1e18);

注意:C++17 之前的 __gcd 是 GCC 扩展;严谨代码自己写欧几里得

long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }

随机数(<random> 配合使用)#

<random> 虽不在 <numeric> 里,但常一起用。告别 rand()——rand() 范围小、质量差、且依赖实现。

#include <random>
#include <ctime>
mt19937 rng(time(nullptr)); // 32 位引擎
mt19937_64 rng64(chrono::steady_clock::now().time_since_epoch().count()); // 64 位
// 范围 [lo, hi] 均匀整数
uniform_int_distribution<int> dist(1, 100);
int x = dist(rng);
// 范围 [0, 1) 均匀浮点
uniform_real_distribution<double> fdist(0.0, 1.0);
double y = fdist(rng);
// 容器洗牌
shuffle(v.begin(), v.end(), rng);
引擎位数用途
mt1993732通用、够用
mt19937_6464大范围 ID、需要 64 位
default_random_engine视实现不推荐(质量参差)

关键注意点#

易错点说明
accumulate 初始值用 0大数累加用 0LL 防溢出
partial_sum 含当前项想要”前 i-1 项和”用 exclusive_scan
iota 不检查越界区间要先 resize
gcd / lcmC++17 起,旧编译器用 __gcd 或手写
rand()范围小、质量差,统一换 mt19937
shuffle 需要引擎mt19937,不能传 time(nullptr)

iomanip#

<iomanip> 提供格式化输出的”操控器”(manipulator),用来控制 cout 的宽度、精度、对齐、进制等。默认状态不会持久化——除了 fixed / scientific / boolalpha 等”标志型”,像 setw 这种只对下一次输出生效。

精度与浮点格式#

操控器作用备注
setprecision(n)设置精度(有效数字位数默认模式
setprecision(n) + fixed设置小数位数刷题最常考
setprecision(n) + scientific设置科学计数法的小数位数
defaultfloat还原默认(C++11)退出 fixed 模式
showpoint / noshowpoint强制 / 不强制显示小数点
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double pi = 3.14159265358979;
cout << setprecision(4) << pi << endl; // 3.142(4 位有效数字)
cout << fixed << setprecision(2) << pi << endl; // 3.14(保留 2 位小数)
cout << defaultfloat << setprecision(6) << pi; // 3.14159
// 默认 cout 输出 1.0 会显示 1,showpoint 强制显示 1.00000
cout << fixed << setprecision(2);
cout << 1.0 << endl; // 1.00
return 0;
}

注意fixed / scientific持久的,影响后续所有浮点输出;用完想还原要 cout << defaultfloat;(C++11)。

宽度与填充#

操控器作用备注
setw(n)设置下一次输出的最小宽度只生效一次
setfill(c)设置填充字符(默认空格)持久
left / right左对齐 / 右对齐(默认 right)持久
internal符号左对齐、数值右对齐(如 - 123持久
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
// 题目要求:输出 4 位整数,不足补 0(如 1 → 0001)
cout << setfill('0');
for (int i = 1; i <= 5; i++) {
cout << setw(4) << i << endl;
}
// 0001
// 0002
// 0003
// 0004
// 0005
// 对齐:左对齐 + 宽度 10,填充 *
cout << setfill('*') << left << setw(10) << "hi" << "end" << endl;
// hi********end
return 0;
}

⚠ 警告setw 只对下一次输出生效!多个字段都要设宽度时,必须每次都写 setw

进制与布尔#

操控器作用
hex / dec / oct十六进制 / 十进制 / 八进制(持久)
setbase(n)进制(只接受 8/10/16,其余按 10 处理)
showbase / noshowbase显示 / 不显示进制前缀(0x / 0
uppercase / nouppercase十六进制字母大写 / 小写
boolalpha / noboolalphabool 输出 true / false 还是 1 / 0
cout << hex << 255; // ff
cout << showbase << hex << 255; // 0xff
cout << uppercase << hex << 255; // 0XFF
bool flag = true;
cout << flag; // 1
cout << boolalpha << flag; // true

输入侧操控器#

操控器作用
ws跳过前导空白字符(常用于 getline 前清空残留换行)
get_money(m) / put_money(m)货币格式(C++11,少用)
get_time(t, fmt) / put_time(t, fmt)时间格式(C++11,少用)
int n;
string s;
cin >> n;
// >> 之后缓冲区留有 '\n',getline 会读空串
cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin, s);

注意:刷题最常见的坑cin >> n 后接 getline(cin, s) 读到空串,必须 cin.ignore 清除残留换行。

关键注意点#

易错点说明
setw 只生效一次多个字段必须每次都写
setprecision 默认是有效数字想保留 n 位小数要加 fixed
fixed 持久生效用完记得 defaultfloat 还原
cout << bool 输出 0/1想看 true/falseboolalpha
hex 也持久想回十进制要 dec
cin >> n + getline记得 cin.ignore() 清残留换行

极限宏#

宏名称对应类型值(十进制)用途
INT_MAXint2,147,483,647int 最大值
INT_MINint-2,147,483,648int 最小值
LLONG_MAXlong long9,223,372,036,854,775,807long long 最大值
LLONG_MINlong long-9,223,372,036,854,775,808long long 最小值
ULLONG_MAXunsigned long long18,446,744,073,709,551,615unsigned long long 最大值
LONG_MAXlongWindows: 2,147,483,647
Linux: 9,223,372,036,854,775,807
长度随平台,刷题不推荐
LONG_MINlongWindows: -2,147,483,648
Linux: -9,223,372,036,854,775,808
同上

整型字面量后缀(无需头文件)#

后缀类型示例用途
无后缀int123默认整型
Llong123L不推荐(平台相关)
LLlong long123LL明确 64 位有符号
ULLunsigned long long123ULL明确 64 位无符号
uunsigned int123u无符号 int
ffloat3.14f单精度浮点

⚠️ 刷题最常用1LL * a * b 防止乘法溢出。

C++ 常用头文件
https://xianhe51920.github.io/posts/cpp-headers/
作者
仙鹤
发布于
2026-09-03
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取

评论

正在加载评论...