GESP七级通关秘籍(选择判断题)

gesp c++ 七级知识点 阅读详情

GESP C++七级核心知识点详解

一、数学库函数(三角函数、对数函数、指数函数)

通俗解释

C++ 中的数学库函数(需包含头文件 <cmath>)是预定义的常用数学计算工具,能直接实现三角、对数、指数等复杂运算,无需手动编写计算逻辑,核心用于快速解决数学相关问题(如几何计算、数据建模等)。

  • 三角函数:sin(x)(正弦)、cos(x)(余弦)等,输入参数为弧度(而非角度),返回对应三角函数值;
  • 对数函数:log10(x) 返回 x 以 10 为底的对数,log2(x) 返回 x 以 2 为底的对数(C++11 及以上支持);
  • 指数函数:exp(x) 返回 e 的 x 次方(e 是自然常数,约 2.71828)。

C++ 例题

#include <iostream>
#include <cmath>  // 必须包含数学库头文件
using namespace std;

int main() {
    // 1. 三角函数:计算 30 度的正弦值(需先转弧度)
    double angle_deg = 30.0;
    double angle_rad = angle_deg * M_PI / 180.0;  // 角度转弧度:弧度 = 角度 × π / 180
    double sin_val = sin(angle_rad);
    cout << "30度的正弦值:" << sin_val << endl;  // 输出约 0.5

    // 2. 对数函数:计算 log10(100)(10的2次方=100)
    double log10_val = log10(100.0);
    cout << "log10(100) = " << log10_val << endl;  // 输出 2.0

    // 3. 指数函数:计算 exp(1)(e的1次方≈2.71828)
    double exp_val = exp(1.0);
    cout << "exp(1) = " << exp_val << endl;  // 输出约 2.71828

    return 0;
}

重点

  1. 必须包含头文件 <cmath>,否则无法调用数学库函数;
  2. 牢记各函数的参数要求(如三角函数输入弧度)和返回值类型(通常为 double);
  3. 熟悉常用常量 M_PI(π,需开启 C++11 及以上标准)。

难点

  1. 角度与弧度的转换逻辑(容易忘记转换直接输入角度,导致结果错误);
  2. 对数函数的底数区分(log(x) 是自然对数 ln(x),而非以 10 为底,需注意与 log10(x) 区分)。

易错点

  1. 直接将角度传入三角函数(如 sin(30) 会计算 30 弧度的正弦值,结果完全错误);
  2. 遗漏 <cmath> 头文件或未开启 C++11 标准(导致 log2(x)、M_PI 无法使用);
  3. 用 int 类型接收返回值(如 int res = sin(angle_rad),会丢失小数部分,导致精度错误)。

二、复杂动态规划(二维DP、区间DP、LIS、LCS、滚动数组优化)

通俗解释

动态规划(DP)是一种“拆分大问题、记录小答案、避免重复计算”的解题思想。复杂动态规划聚焦更复杂的场景:

  • 二维DP:用二维数组记录“两个维度相关”的小问题答案(如“前 i 个物品放入容量 j 的背包”);
  • 区间DP:专门解决“区间相关”问题(如“字符串区间的最长回文子串”“数组区间的最大和”),核心是“从短区间扩展到长区间”;
  • LIS(最长上升子序列):在一串数字中找“不下降(或严格上升)且最长”的子序列(子序列不要求连续);
  • LCS(最长公共子序列):在两个字符串/数组中找“最长且顺序一致”的公共子序列(不要求连续);
  • 滚动数组优化:将二维DP数组压缩为一维,减少内存占用(核心是“后一个状态只依赖前一个状态”)。

C++ 例题(经典核心题型)

1. 最长上升子序列(LIS)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> nums = {10, 9, 2, 5, 3, 7, 101, 18};  // 输入序列
    int n = nums.size();
    vector<int> dp(n, 1);  // dp[i] 表示:以 nums[i] 结尾的最长上升子序列长度(初始为1,自身是子序列)

    // 状态转移:遍历每个元素,对比前面所有元素
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (nums[j] < nums[i]) {  // 严格上升
                dp[i] = max(dp[i], dp[j] + 1);  // 更新最长长度
            }
        }
    }

    int lis_len = *max_element(dp.begin(), dp.end());  // 找 dp 数组的最大值
    cout << "最长上升子序列长度:" << lis_len << endl;  // 输出 4(子序列:2,3,7,101 或 2,5,7,101 等)
    return 0;
}
2. 最长公共子序列(LCS)
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main() {
    string s1 = "ABCBDAB";
    string s2 = "BDCAB";
    int m = s1.size(), n = s2.size();

    // dp[i][j] 表示:s1前i个字符和s2前j个字符的最长公共子序列长度
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

    // 状态转移
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (s1[i - 1] == s2[j - 1]) {  // 字符相同,长度+1
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {  // 字符不同,取前两种情况的最大值
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }

    cout << "最长公共子序列长度:" << dp[m][n] << endl;  // 输出 4(子序列:BCAB 或 BDAB 等)
    return 0;
}
3. 滚动数组优化(LCS 优化为一维DP)
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main() {
    string s1 = "ABCBDAB";
    string s2 = "BDCAB";
    int m = s1.size(), n = s2.size();

    vector<int> dp(n + 1, 0);  // 一维数组,节省空间

    for (int i = 1; i <= m; i++) {
        int prev = 0;  // 保存 dp[i-1][j-1] 的值(避免被覆盖)
        for (int j = 1; j <= n; j++) {
            int temp = dp[j];  // 暂存当前 dp[j](即 dp[i-1][j])
            if (s1[i - 1] == s2[j - 1]) {
                dp[j] = prev + 1;
            } else {
                dp[j] = max(dp[j], dp[j - 1]);
            }
            prev = temp;  // 更新 prev 为下一轮的 dp[i-1][j-1]
        }
    }

    cout << "最长公共子序列长度(滚动数组优化):" << dp[n] << endl;  // 输出 4
    return 0;
}

重点

  1. 动态规划的核心:状态定义(明确 dp[i] 或 dp[i][j] 表示什么)和 状态转移方程(如何从子问题答案推导当前问题答案);
  2. LIS 和 LCS 是必考经典题型,需牢记基础状态转移逻辑;
  3. 滚动数组优化的核心是“识别状态依赖关系”(如 LCS 中 dp[i][j] 只依赖 dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1])。

难点

  1. 状态定义不准确(如 LIS 中误将 dp[i] 定义为“前 i 个元素的最长上升子序列长度”,而非“以第 i 个元素结尾”);
  2. 状态转移方程推导错误(尤其是区间 DP,需明确区间扩展逻辑);
  3. 滚动数组优化时,未正确保存“被覆盖的前一状态”(导致数据丢失)。

易错点

  1. DP 数组初始化错误(如 LIS 中未将 dp[i] 初始化为 1,导致长度计算偏小);
  2. 数组下标越界(如字符串处理时,混淆 s[i] 和 s[i-1],因为 DP 数组通常从 1 开始索引);
  3. 区间 DP 中“区间长度的遍历顺序错误”(应从短区间到长区间,而非从左到右遍历节点);
  4. 滚动数组优化时,忘记用临时变量保存前一状态(如 LCS 中直接覆盖 dp[j],导致 dp[i-1][j-1] 丢失)。

三、图的定义及遍历(图的概念、存储、BFS、DFS)

通俗解释

图是由“节点”(如城市)和“边”(如城市间的道路)组成的结构,是描述多元素关联关系的工具:

  • 图的分类:无向图(边无方向,如双向道路)、有向图(边有方向,如单向车道);
  • 节点的度:无向图中节点连接的边数,有向图中分为入度(指向节点的边数)和出度(离开节点的边数);
  • 图的存储:C++ 中常用两种方式——邻接矩阵(二维数组,适合节点少、边多的稠密图)、邻接表(vector 数组,适合节点多、边少的稀疏图);
  • BFS(广度优先搜索):“逐层扩散”的遍历方式,像“水波涟漪”,用队列实现,适合找“最短路径”(无权重图);
  • DFS(深度优先搜索):“一条路走到黑”的遍历方式,像“迷宫探险”,用递归或栈实现,适合找“所有路径”或“连通块”。

C++ 例题(邻接表存储 + BFS + DFS)

#include <iostream>
#include <vector>
#include <queue>
#include <visited>  // 注意:实际中用数组标记访问,此处为笔误,应为手动定义visited数组
using namespace std;

vector<vector<int>> adj;  // 邻接表:adj[u] 存储 u 直接相连的节点
vector<bool> visited;     // 标记节点是否已访问

// DFS 递归实现
void dfs(int u) {
    visited[u] = true;
    cout << u << " ";  // 输出当前访问的节点
    // 遍历所有与 u 相连的未访问节点
    for (int v : adj[u]) {
        if (!visited[v]) {
            dfs(v);
        }
    }
}

// BFS 队列实现
void bfs(int start) {
    queue<int> q;
    q.push(start);
    visited[start] = true;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        cout << u << " ";  // 输出当前访问的节点
        // 遍历所有与 u 相连的未访问节点,加入队列
        for (int v : adj[u]) {
            if (!visited[v]) {
                visited[v] = true;
                q.push(v);
            }
        }
    }
}

int main() {
    int n = 5;  // 节点数(0~4)
    int m = 6;  // 边数
    adj.resize(n);
    // 无向图的边(0-1, 0-2, 1-3, 1-4, 2-4, 3-4)
    adj[0].push_back(1);
    adj[1].push_back(0);
    adj[0].push_back(2);
    adj[2].push_back(0);
    adj[1].push_back(3);
    adj[3].push_back(1);
    adj[1].push_back(4);
    adj[4].push_back(1);
    adj[2].push_back(4);
    adj[4].push_back(2);
    adj[3].push_back(4);
    adj[4].push_back(3);

    // 测试 DFS
    cout << "DFS 遍历结果:";
    visited.assign(n, false);  // 初始化访问标记
    dfs(0);  // 从节点 0 开始
    cout << endl;  // 输出:0 1 3 4 2(或其他顺序,取决于邻接表存储顺序)

    // 测试 BFS
    cout << "BFS 遍历结果:";
    visited.assign(n, false);  // 重置访问标记
    bfs(0);  // 从节点 0 开始
    cout << endl;  // 输出:0 1 2 3 4(逐层扩散,顺序固定)

    return 0;
}

重点

  1. 掌握图的两种存储方式(邻接矩阵、邻接表)的适用场景和实现;
  2. 理解 BFS 和 DFS 的核心思想(逐层 vs 深度)和实现工具(队列 vs 递归/栈);
  3. 遍历前必须初始化“访问标记数组”(避免重复访问节点)。

难点

  1. 邻接表的构建逻辑(尤其是有向图,需区分“起点”和“终点”);
  2. DFS 递归深度过大导致栈溢出(需用迭代版 DFS 优化);
  3. 结合实际问题设计图的存储(如节点是字符串时,需用哈希表映射为整数索引)。

易错点

  1. 忘记标记访问节点(导致无限循环,程序崩溃);
  2. 邻接表构建时“漏加边”(如无向图只加了 u→v,没加 v→u);
  3. 节点编号从 1 开始,但数组初始化从 0 开始(导致下标越界);
  4. BFS 中未在“加入队列时”标记访问(而是在“弹出队列时”标记,导致同一节点多次入队,效率低下)。

四、泛洪算法(Flood Fill)

通俗解释

泛洪算法是图遍历的一种特殊应用,核心是“从一个起点出发,将所有‘相邻且满足条件’的节点标记为同一类”,像“洪水从起点蔓延,淹没所有可达的区域”。常见应用:图像填色(如 Photoshop 魔棒工具)、连通块查找(如找出二维数组中所有相连的 1)。C++ 中通常用 BFS 或 DFS 实现。

C++ 例题(二维数组连通块填充)

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

// 方向数组:上下左右四个方向
int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

// BFS 实现泛洪填充
void floodFillBFS(vector<vector<int>>& grid, int x, int y, int oldVal, int newVal) {
    int m = grid.size(), n = grid[0].size();
    if (grid[x][y] != oldVal) return;  // 起点不满足条件,直接返回

    queue<pair<int, int>> q;
    q.push({x, y});
    grid[x][y] = newVal;  // 标记为新值(避免重复访问)

    while (!q.empty()) {
        auto [curX, curY] = q.front();
        q.pop();
        // 遍历四个方向
        for (auto& dir : dirs) {
            int nx = curX + dir[0];
            int ny = curY + dir[1];
            // 边界判断 + 满足旧值条件
            if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == oldVal) {
                grid[nx][ny] = newVal;
                q.push({nx, ny});
            }
        }
    }
}

int main() {
    // 二维数组表示图像(1 表示需填充的区域,0 表示边界)
    vector<vector<int>> grid = {
        {1, 1, 1},
        {1, 1, 0},
        {1, 0, 1}
    };

    floodFillBFS(grid, 0, 0, 1, 2);  // 从 (0,0) 出发,将所有 1 改为 2

    // 输出填充后的结果
    cout << "填充后的二维数组:" << endl;
    for (auto& row : grid) {
        for (int val : row) {
            cout << val << " ";
        }
        cout << endl;
    }
    /* 输出:
    2 2 2
    2 2 0
    2 0 2
    */
    return 0;
}

重点

  1. 方向数组的定义(上下左右四个方向,避免漏写或写错);
  2. 边界判断(确保访问的节点在二维数组内,不越界);
  3. 标记逻辑(填充时直接修改原值为新值,或用单独的访问数组,避免重复处理)。

难点

  1. 多连通块的处理(需遍历所有未标记的节点,逐个作为起点泛洪);
  2. 复杂条件的判断(如“相邻”定义为“8个方向”,或填充条件为“值在某个区间内”);
  3. 大规模数据的效率优化(如二维数组过大时,BFS 比 DFS 更稳定,避免栈溢出)。

易错点

  1. 方向数组写错(如写成 {0,1}, {0,-1} 只处理左右,漏了上下);
  2. 边界判断遗漏(如只判断 nx < m,没判断 nx >= 0,导致下标越界);
  3. 未及时标记已处理的节点(导致同一节点多次入队,程序超时或崩溃);
  4. 起点坐标错误(如输入 (x,y) 时混淆行和列,导致填充失败)。

五、哈希表(概念与应用)

通俗解释

哈希表是一种“键值对”存储结构,核心是“通过哈希函数将‘键’(如学生学号)映射到数组的索引,快速查找对应‘值’(如学生姓名)”。C++ 中常用哈希表容器:

  • unordered_map:存储键值对(key-value),键唯一,查找、插入、删除效率约 O(1)(理想情况);
  • unordered_set:只存储键(key),键唯一,用于快速判断某个元素是否存在。
    哈希表的优势是“无需排序,直接通过键访问”,比普通数组(需按索引访问)、有序容器(如 map,O(log n) 效率)更高效。

C++ 例题(unordered_map 统计字符出现次数)

#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;

int main() {
    string s = "abacaba";
    unordered_map<char, int> charCount;  // 键:字符,值:出现次数

    // 遍历字符串,统计次数
    for (char c : s) {
        charCount[c]++;  // 键不存在时,默认值为 0,++ 后变为 1
    }

    // 遍历哈希表,输出结果
    cout << "字符出现次数:" << endl;
    for (auto& pair : charCount) {
        cout << pair.first << ": " << pair.second << endl;
    }
    /* 输出(顺序不固定,因为 unordered_map 无序):
    a: 4
    b: 2
    c: 1
    */

    // 查找某个字符的次数
    char target = 'a';
    if (charCount.find(target) != charCount.end()) {
        cout << target << " 出现了 " << charCount[target] << " 次" << endl;
    } else {
        cout << target << " 未出现" << endl;
    }

    return 0;
}

重点

  1. 掌握 unordered_map 和 unordered_set 的基本操作:insert()(插入)、find()(查找)、erase()(删除)、遍历;
  2. 理解哈希表的核心优势(快速访问,O(1) 平均时间复杂度);
  3. 明确键的唯一性(unordered_map 和 unordered_set 中键不能重复,重复插入会覆盖或失败)。

难点

  1. 哈希冲突的理解(多个键映射到同一索引,C++ 内部通过“链地址法”解决,但无需手动处理);
  2. 自定义类型作为键(需重载哈希函数和 == 运算符,考纲中较少涉及,了解即可);
  3. 哈希表与有序容器(map/set)的选择(需有序时用 map,无需有序时用 unordered_map 更高效)。

易错点

  1. 访问 unordered_map 中不存在的键(会自动插入该键,值为默认值,导致统计错误,需用 find() 先判断是否存在);
  2. 混淆 unordered_map 和 map(前者无序、哈希实现,后者有序、红黑树实现,效率和用途不同);
  3. 遍历哈希表时依赖顺序(unordered_map 无序,如需有序输出,需存入数组后排序);
  4. 键的类型选择错误(如用 vector<int> 作为键,未自定义哈希函数,导致编译错误)。
GESP C++ 一级到八级通关秘籍:从零基础到算法高手的学习路线图 本文系统梳理了GESP C++一级到八级的完整学习路线图,为从零基础到算法高手的成长提供了清晰的阶梯式规划。内容涵盖从基础语法、数据结构到高级算法(如动态规划、图论)的核心知识与实战技巧,帮助考生和自学者高效备考与进阶,是掌握C++编程与算法思维的权威指南。 阅读详情

相关推荐

2024年3月GESP真题及题解(C++八级): 接竹竿

2024年3月GESP真题及题解(C++八级): 接竹竿

王老师青少年编程 986

2026年9月GESP真题及题解(C++七级):必经之路

2026年9月GESP真题及题解(C++七级):必经之路

王老师青少年编程 389

操作系统笔记(含王道计算机考研——操作系统课件)

操作系统(OS) 笔记根据B站王道计算机考研——操作系统视频整理所得,视频链接:https://b23.tv/0I2qex 视频中所用课件:链接:https://pan.baidu.com/s/101bFWm0Tv0emNpEneidYPA 提取码:y3dd 1.计算机系统概述 1.简介 什么是操作系统? 操作系统(Operating Ststem, OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境,它是

拧发条鸟的博客 6万+

STM32----SPI+DMA高效读写外部Flash的配置与实战

本文详细介绍了STM32通过SPI+DMA高效读写外部Flash的配置与实战方法。针对大量数据传输场景,使用DMA技术可显著提升系统效率,释放CPU资源。文章包含完整的代码实现、常见问题调试技巧以及性能优化建议,帮助开发者快速掌握这一关键技术。

pea55的博客 1022

离线安装 nvidia-docker2(nvidia-container-toolkit)

很多时候大家都有用docker使用gpu的需求,但是因为网络等原因不是那么好用,这里留了一个给ubuntu的安装包,网络好的话也提供了在线安装方式。

father_yingying的博客 1176

YOLOv8改进:基于EfficientNetV2均衡缩放网络的特征提取层优化【YOLOv8】

YOLO(You Only Look Once)系列模型以其高效的实时目标检测能力而闻名。YOLOv8作为该系列的最新版本,通过引入改进的网络结构和算法优化,进一步提升了目标检测的性能。然而,YOLOv8在特征提取阶段的网络结构仍有改进的空间。EfficientNetV2是一种基于均衡缩放的卷积神经网络,它通过优化网络的宽度、深度和分辨率来实现高效的特征提取。与之前的EfficientNet版本相比,EfficientNetV2在速度和精度上都有显著提升,尤其在处理复杂目标检测任务时表现尤为突出。

博客 1572

TC3XX - MCAL知识点(三十八):AURIX™ TC3xx 的EDSADC实现旋变解码功能(理论知识+手册阅读)

本文系统梳理了英飞凌AURIX系列芯片EDSADC模块的技术手册内容。首先概述了该模块的架构特点,包括模拟/数字输入通道和总线地址信息。重点解析了手册中的关键知识点:1)模拟量输入的差分/单端模式;2)数字量连接的触发、数据源和时钟源选择;3)功能配置中的寄存器操作注意事项;4)输入通道的三种数据来源模式;5)滤波器链的组成和工作原理;6)旋变应用中的载波信号生成和延迟补偿机制。最后对SRM、SAUL、SBLL等专业术语进行了详细解释。全文为理解EDSADC模块的硬件特性和配置方法提供了系统的技术参考。

梦想技术家 577

FOC 转子初始位置检测(图文详解)

什么是转子的初始位置? 其实转子的初始位置是不确定的,但是在电机启动的时候,我们需要得到电角度,这样才可以进行矢量控制;所以,这里将转子与A轴重合作为初始位置,此时电角度也恰好为零,具体如下图所示; ) 至于原理下面会详细分析,这样在转子到初始位置后,也可以得到准确的电角度,就可以实现磁场和转子的同步转动。 如何让转子运行到初始位置? 其实这是一个很简单的问题,在这里我将它放大了,简单地分析了一...

一名热爱技术的工程师的博客。分享技术干货,记录美好生活。永远相信美好的事情即将发生。 2万+

大模型复杂问答能力评测框架:从原理到实践

在人工智能领域,大语言模型(LLM)的评估是衡量其实际应用价值的关键环节。其核心原理在于通过系统化的评测框架,对模型的理解、推理、整合与表达能力进行量化分析。传统的NLP基准测试往往侧重于事实性检索或简单推理,难以全面反映模型在应对多跳推理、隐含条件、长上下文整合等复杂现实任务时的真实性能。因此,专门针对复杂问答设计的评测技术应运而生,其价值在于为模型选型、效果优化和瓶颈诊断提供数据驱动的科学依据。该技术广泛应用于需要深度逻辑判断的业务场景,如智能投顾、法律咨询、医疗诊断等。本文聚焦的`tan92hl/Co

weixin_28679635的博客 357

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

上一篇: GESP六级通关秘籍(选择判断题)
下一篇: GESP八级通关秘籍(选择判断题)
信奥源老师
博客等级 码龄16年 2454粉丝 297原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信奥源老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值