diff --git a/NOI_Beginner_Guide_2025.html b/NOI_Beginner_Guide_2025.html new file mode 100644 index 0000000..efae208 --- /dev/null +++ b/NOI_Beginner_Guide_2025.html @@ -0,0 +1,1446 @@ + + +
+ +基于 NOI 大纲(2025年修订版) | 含全网调研AI重评分 | 详细知识点讲解与代码示例
+ +原始评分【1】→ AI重评【2】(基础重要,竞赛环境必备)
+计算机系统由硬件和软件两大部分组成。硬件是计算机的物理组成部分,主要包括以下核心组件:
+| 组件 | 功能说明 | 竞赛关注点 |
|---|---|---|
| CPU(中央处理器) | 执行指令和运算的核心部件,包含运算器和控制器 | 理解时间复杂度的物理基础 |
| 内存(RAM) | 临时存储正在运行的程序和数据,断电后数据丢失 | 理解空间复杂度、数组大小限制 |
| 外存(硬盘/SSD) | 永久存储数据和程序 | 文件读写操作的基础 |
| 输入设备 | 键盘、鼠标等,用于向计算机输入数据 | 标准输入(stdin) |
| 输出设备 | 显示器、打印机等,用于输出处理结果 | 标准输出(stdout) |
原始评分【1】→ AI重评【2】(环境操作基础,实用性提升)
+操作系统(Operating System, OS)是管理计算机硬件和软件资源的系统软件。NOI竞赛环境主要使用Linux操作系统(NOI Linux 2.0,基于Ubuntu 20.04)。选手需要了解操作系统的基本功能:进程管理、内存管理、文件系统管理和设备管理。
+ +难度评级【1】
+了解计算机网络的基本概念,包括局域网(LAN)、广域网(WAN)、Internet的基本架构、IP地址、域名系统(DNS)等。此部分在CSP-J初赛中偶有考察。
+ +难度评级【1】
+了解计算机发展的重要里程碑:从ENIAC(1946年)到现代计算机。了解图灵(Alan Turing)、冯·诺依曼(John von Neumann)等计算机科学先驱的贡献。冯·诺依曼体系结构(存储程序概念)是现代计算机的基础架构。
+ +难度评级【1】
+NOI(全国青少年信息学奥林匹克竞赛)由中国计算机学会(CCF)主办。竞赛体系包括:CSP-J/S(非专业级软件能力认证)→ NOIP(联赛)→ NOI(国赛)→ IOI(国际赛)。CSP-J为入门级认证,面向初中及以下学生。
+ +原始评分【1】→ AI重评【3】(位运算基础,竞赛常用)
+计算机中数据的最小单位是位(bit),只能存储0或1。8个位组成一个字节(Byte)。字(Word)的大小取决于CPU架构(32位或64位)。
+| 单位 | 大小 | 常见应用 |
|---|---|---|
| 1 bit | 0 或 1 | bool类型的逻辑值 |
| 1 Byte = 8 bits | 0~255(无符号) | char类型 |
| 4 Bytes = 32 bits | 约±21亿 | int类型 |
| 8 Bytes = 64 bits | 约±9.2×1018 | long long类型 |
long long类型的题目。当数据范围超过2×109时,必须使用long long。原始评分【1】→ AI重评【2】(理解编译流程重要)
+程序设计语言分为低级语言(机器语言、汇编语言)和高级语言(C、C++、Python等)。NOI系列竞赛使用C++语言。C++程序需要经过编译(将源代码转换为机器代码)才能运行,编译器将.cpp源文件编译为可执行文件。
难度评级【1】
+掌握在Windows或Linux图形界面中进行文件和目录的基本操作:创建、复制、移动、删除、重命名文件和文件夹。
+ +原始评分【1】→ AI重评【2】(开发环境熟悉度重要)
+常用的C++ IDE包括:Windows下的Dev-C++(轻量级,适合入门)、Code::Blocks(跨平台)、Visual Studio Code(功能强大)。Linux下可使用Code::Blocks或命令行编辑器(如vim、nano)配合g++编译器。
+ +原始评分【1】→ AI重评【3】(编译命令基础,实用性强)
+g++是GNU C++编译器,是NOI竞赛环境中的标准编译器。基本使用方法:
++# 基本编译 +g++ -o program source.cpp + +# 带优化的编译(竞赛常用) +g++ -O2 -o program source.cpp + +# 编译并启用C++14标准 +g++ -std=c++14 -O2 -o program source.cpp + +# 运行程序 +./program ++ + + +
原始评分【1】→ AI重评【3】(编程基础,必备知识)
+标识符是程序中用来命名变量、函数、类型等的名称,由字母、数字和下划线组成,不能以数字开头。关键字是C++语言保留的具有特殊含义的标识符(如int、if、for、return等),不能用作变量名。
+// 合法标识符 +int count = 0; +double totalScore = 95.5; +int _value = 10; + +// 非法标识符 +// int 2nd = 5; // 不能以数字开头 +// int class = 1; // class是关键字 ++ +
原始评分【1】→ AI重评【3】(基础语法,重要性提升)
+常量是程序运行期间值不会改变的量,使用const关键字定义。变量是可以在程序运行过程中改变其值的量。
+const int MAXN = 100005; // 常量,竞赛中常用于定义数组大小 +const double PI = 3.14159265358979; +int n, m; // 变量 ++ +
原始评分【2】→ AI重评【3】(代码组织关键)
+头文件包含了函数声明和宏定义。竞赛中常用#include <bits/stdc++.h>万能头文件(包含所有标准库)。名字空间用于避免命名冲突,竞赛中常用using namespace std;。
+#include <bits/stdc++.h> // 万能头文件(竞赛专用)
+using namespace std; // 使用标准命名空间
+
+int main() {
+ // 程序代码
+ return 0;
+}
+
+
+原始评分【2】→ AI重评【3】(调试能力重要)
+编辑是编写源代码的过程。编译是将源代码翻译成机器代码的过程(C++使用编译方式)。解释是逐行翻译并执行源代码(如Python)。调试是查找和修复程序错误的过程。
+ +原始评分【1】→ AI重评【3】(类型理解基础)
+| 类型 | 大小 | 范围 | 用途 |
|---|---|---|---|
int | 4字节 | -231 ~ 231-1(约±2.1×109) | 常规整数 |
long long | 8字节 | -263 ~ 263-1(约±9.2×1018) | 大整数 |
float | 4字节 | 约7位有效数字 | 单精度浮点(少用) |
double | 8字节 | 约15位有效数字 | 双精度浮点 |
char | 1字节 | -128 ~ 127 或 0 ~ 255 | 字符 |
bool | 1字节 | true(1) 或 false(0) | 逻辑值 |
long long,导致整数溢出。建议养成习惯:看到大数据范围立即使用long long。原始评分【2】→ AI重评【3】(IO基础,频繁使用)
+
+#include <bits/stdc++.h>
+using namespace std;
+int main() {
+ int n;
+ // C++风格输入输出
+ cin >> n;
+ cout << "n = " << n << endl;
+
+ // C风格输入输出(通常更快)
+ scanf("%d", &n);
+ printf("n = %d\n", n);
+
+ return 0;
+}
+
+scanf/printf比cin/cout更快。如果使用cin/cout,可以添加ios::sync_with_stdio(false); cin.tie(0);来加速。原始评分【2】→ AI重评【3】(控制流基础)
+
+// if-else语句
+if (score >= 90) {
+ cout << "优秀" << endl;
+} else if (score >= 60) {
+ cout << "及格" << endl;
+} else {
+ cout << "不及格" << endl;
+}
+
+// switch语句
+switch (grade) {
+ case 'A': cout << "优秀"; break;
+ case 'B': cout << "良好"; break;
+ default: cout << "其他"; break;
+}
+
+
+原始评分【2】→ AI重评【3】(循环结构核心)
+
+// for循环 - 最常用
+for (int i = 0; i < n; i++) {
+ // 循环体
+}
+
+// while循环
+while (条件) {
+ // 循环体
+}
+
+// do-while循环(至少执行一次)
+do {
+ // 循环体
+} while (条件);
+
+
+原始评分【3】→ AI重评【4】(复杂度提升,常见考点)
+多层循环(嵌套循环)在竞赛中非常常见,用于处理二维数组、枚举多个变量等场景。需要注意时间复杂度:两层循环为O(n2),三层为O(n3)。
+
+// 打印九九乘法表
+for (int i = 1; i <= 9; i++) {
+ for (int j = 1; j <= i; j++) {
+ printf("%d×%d=%-3d", j, i, i * j);
+ }
+ printf("\n");
+}
+
+
+原始评分【1】→ AI重评【3】(运算基础,频繁使用)
+| 运算类型 | 运算符 | 示例 | 说明 |
|---|---|---|---|
| 算术运算 | + - * | a + b | 加减乘 |
/ | 7 / 2 = 3 | 整数除法取整 | |
% | 7 % 2 = 1 | 取余(模运算) | |
++ -- | i++ | 自增自减 | |
?: | a>b ? a : b | 三目运算 | |
| 关系运算 | > >= < <= == != | a == b | 返回bool值 |
| 逻辑运算 | && || ! | a>0 && b>0 | 与、或、非 |
原始评分【2】→ AI重评【5】(高频考点,难度较大)
+位运算直接操作二进制位,在竞赛中应用广泛(状态压缩、快速判断奇偶等)。
+| 运算符 | 名称 | 示例 | 结果 | 常见用途 |
|---|---|---|---|---|
& | 按位与 | 5 & 3 (101 & 011) | 1 (001) | 判断奇偶:n & 1 |
| | 按位或 | 5 | 3 (101 | 011) | 7 (111) | 设置某一位 |
^ | 按位异或 | 5 ^ 3 (101 ^ 011) | 6 (110) | 交换两数、加密 |
~ | 按位取反 | ~5 | -6 | 补码运算 |
<< | 左移 | 1 << 3 | 8 | 乘以2的幂 |
>> | 右移 | 8 >> 2 | 2 | 除以2的幂 |
+// 位运算常见技巧 +int n = 10; +if (n & 1) cout << "奇数"; else cout << "偶数"; // 判断奇偶 +int x = 1 << 10; // x = 1024,即2^10 +// 交换两个数(不用临时变量) +a ^= b; b ^= a; a ^= b; ++ +
原始评分【3】→ AI重评【4】(数学思维增强)
+| 函数 | 功能 | 示例 |
|---|---|---|
abs(x) | 绝对值 | abs(-5) = 5 |
sqrt(x) | 平方根 | sqrt(16) = 4.0 |
ceil(x) | 上取整 | ceil(3.2) = 4 |
floor(x) | 下取整 | floor(3.8) = 3 |
round(x) | 四舍五入 | round(3.5) = 4 |
pow(x,y) | x的y次方 | pow(2,10) = 1024 |
log(x) | 自然对数 | log(e) = 1.0 |
log2(x) | 以2为底的对数 | log2(8) = 3.0 |
原始评分【1】→ AI重评【3】(基础结构,重要性提升) 原始评分【2】→ AI重评【3】(代码组织与设计)
+程序的三种基本结构:顺序结构(按顺序执行)、分支结构(条件判断)、循环结构(重复执行)。模块化程序设计将复杂问题分解为若干子问题,每个子问题用一个函数实现。
+ +原始评分【1】→ AI重评【4】(基础数据结构,应用广)
+数组是存储相同类型元素的连续内存空间。数组下标从0开始。
+
+int a[100005]; // 定义数组,竞赛中通常开大一些
+int n;
+cin >> n;
+for (int i = 0; i < n; i++) {
+ cin >> a[i]; // 读入数组
+}
+// 求数组元素之和
+long long sum = 0;
+for (int i = 0; i < n; i++) {
+ sum += a[i];
+}
+
+
+原始评分【3】→ AI重评【4】(常见数据结构)
++int grid[105][105]; // 二维数组,常用于矩阵、地图 +int n, m; +cin >> n >> m; +for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + cin >> grid[i][j]; ++ +
原始评分【2】→ AI重评【4】(字符串处理基础)
+C++中处理字符串有两种方式:字符数组(C风格)和string类(C++风格,推荐)。
+
+// string类常用操作
+string s = "hello";
+int len = s.length(); // 长度:5
+s += " world"; // 拼接:"hello world"
+string sub = s.substr(0, 5); // 子串:"hello"
+int pos = s.find("world"); // 查找:6
+char c = s[0]; // 访问字符:'h'
+
+// 字符数组
+char str[105];
+scanf("%s", str);
+int len2 = strlen(str);
+
+
+原始评分【2】→ AI重评【5】(递归难点,重要考点)
+
+// 函数定义
+int gcd(int a, int b) {
+ if (b == 0) return a;
+ return gcd(b, a % b); // 递归调用
+}
+
+// 函数调用
+int result = gcd(12, 8); // result = 4
+
+
+原始评分【3】→ AI重评【4】(参数传递细节重要)
+
+// 传值:函数内修改不影响原变量
+void addOne(int x) { x++; }
+
+// 传引用:函数内修改会影响原变量
+void addOne(int &x) { x++; }
+
+int a = 5;
+addOne(a); // 传引用后 a = 6
+
+
+原始评分【3】→ AI重评【4】(数据组织关键)
+
+// 结构体:将不同类型的数据组合在一起
+struct Student {
+ string name;
+ int score;
+ bool operator < (const Student &other) const {
+ return score > other.score; // 按分数降序排序
+ }
+};
+
+Student stu[105];
+sort(stu, stu + n); // 使用自定义排序
+
+
+原始评分【4】→ AI重评【5】(核心难点,区分度高)
+指针存储变量的内存地址,引用是变量的别名。在竞赛中,指针主要用于链表、树等数据结构的实现。
++int x = 10; +int *p = &x; // p指向x的地址 +cout << *p; // 解引用,输出10 +*p = 20; // 通过指针修改x的值 + +int &ref = x; // ref是x的引用(别名) +ref = 30; // 等价于 x = 30 ++ +
原始评分【2】→ AI重评【3】(竞赛中偶尔应用)
+
+// 文件重定向(竞赛常用)
+freopen("input.txt", "r", stdin);
+freopen("output.txt", "w", stdout);
+
+// C++文件流
+ifstream fin("input.txt");
+ofstream fout("output.txt");
+int n;
+fin >> n;
+fout << n << endl;
+
+
+原始评分【3】→ AI重评【5】(高频实用,效率提升)
+
+#include <bits/stdc++.h>
+using namespace std;
+
+int a[] = {3, 1, 4, 1, 5, 9, 2, 6};
+int n = 8;
+
+sort(a, a + n); // 排序:1 1 2 3 4 5 6 9
+sort(a, a + n, greater<int>()); // 降序排序
+int mx = *max_element(a, a + n); // 最大值
+int mn = *min_element(a, a + n); // 最小值
+swap(a[0], a[1]); // 交换两个元素
+reverse(a, a + n); // 反转数组
+
+
+原始评分【4】→ AI重评【6】(竞赛必备,应用广泛)
+| 容器 | 特点 | 常用操作 | 竞赛应用 |
|---|---|---|---|
vector | 动态数组 | push_back, size, [] | 邻接表、动态存储 |
stack | 后进先出 | push, pop, top | 表达式求值、括号匹配 |
queue | 先进先出 | push, pop, front | BFS |
list | 双向链表 | push_back, insert | 频繁插入删除 |
+// vector示例
+vector<int> v;
+v.push_back(10);
+v.push_back(20);
+for (int i = 0; i < v.size(); i++) cout << v[i] << " ";
+
+// stack示例
+stack<int> st;
+st.push(1); st.push(2); st.push(3);
+while (!st.empty()) {
+ cout << st.top() << " "; // 输出 3 2 1
+ st.pop();
+}
+
+// queue示例(BFS常用)
+queue<int> q;
+q.push(1); q.push(2);
+while (!q.empty()) {
+ int front = q.front(); q.pop();
+ cout << front << " "; // 输出 1 2
+}
+
+
+
+
+原始评分【3】→ AI重评【4】(数据结构基础)
+链表是一种动态数据结构,每个节点包含数据域和指针域。与数组相比,链表支持O(1)的插入和删除,但不支持随机访问。
+
+// 静态链表(竞赛常用,避免动态内存分配)
+struct Node {
+ int val, next;
+} nodes[100005];
+int head = -1, cnt = 0;
+
+void insert(int val) { // 头插法
+ nodes[cnt] = {val, head};
+ head = cnt++;
+}
+
+
+原始评分【3】→ AI重评【5】(高频考点,应用广)
+栈是一种后进先出(LIFO)的数据结构。在CSP-J中,栈常用于表达式求值、括号匹配、单调栈等场景。
+
+// 括号匹配示例
+bool isValid(string s) {
+ stack<char> st;
+ for (char c : s) {
+ if (c == '(' || c == '[' || c == '{') st.push(c);
+ else {
+ if (st.empty()) return false;
+ char top = st.top(); st.pop();
+ if (c == ')' && top != '(') return false;
+ if (c == ']' && top != '[') return false;
+ if (c == '}' && top != '{') return false;
+ }
+ }
+ return st.empty();
+}
+
+
+原始评分【3】→ AI重评【5】(高频考点,应用广)
+队列是一种先进先出(FIFO)的数据结构。在CSP-J中,队列是BFS(广度优先搜索)的核心数据结构。
+ +原始评分【3】→ AI重评【5】(基础数据结构)
+树是一种非线性数据结构,由节点和边组成。重要概念包括:根节点、叶子节点(无子节点)、父节点、子节点、深度(根到该节点的路径长度)、高度(该节点到最深叶子的路径长度)。
+ +原始评分【3】→ AI重评【5】(基础树结构)
+二叉树是每个节点最多有两个子节点(左子节点和右子节点)的树。基本性质:
+| 性质 | 描述 |
|---|---|
| 第i层最多节点数 | 2i-1 |
| 深度为k的二叉树最多节点数 | 2k - 1 |
| 叶子节点数 = 度为2的节点数 + 1 | n0 = n2 + 1 |
原始评分【4】→ AI重评【6】(存储实现关键)
+
+// 二叉树的数组存储(适用于完全二叉树)
+int tree[100005]; // tree[1]为根,tree[2i]为左子,tree[2i+1]为右子
+
+// 二叉树的链式存储
+struct TreeNode {
+ int val;
+ int left, right; // 左右子节点编号
+} nodes[100005];
+
+
+原始评分【4】→ AI重评【6】(遍历是基础技能)
+
+// 前序遍历:根 → 左 → 右
+void preorder(int u) {
+ if (u == -1) return;
+ cout << nodes[u].val << " ";
+ preorder(nodes[u].left);
+ preorder(nodes[u].right);
+}
+
+// 中序遍历:左 → 根 → 右
+void inorder(int u) {
+ if (u == -1) return;
+ inorder(nodes[u].left);
+ cout << nodes[u].val << " ";
+ inorder(nodes[u].right);
+}
+
+// 后序遍历:左 → 右 → 根
+void postorder(int u) {
+ if (u == -1) return;
+ postorder(nodes[u].left);
+ postorder(nodes[u].right);
+ cout << nodes[u].val << " ";
+}
+
+
+原始评分【4】→ AI重评【6】(重要树结构)
+完全二叉树是除最后一层外每层都满的二叉树,最后一层的节点从左到右连续排列。可以用数组高效存储:节点i的左子节点为2i,右子节点为2i+1,父节点为i/2。
+ +原始评分【4】→ AI重评【5】(经典算法,应用有限)
+哈夫曼树是带权路径长度最短的二叉树。构造方法:每次取权值最小的两个节点合并。哈夫曼编码是一种最优前缀编码,用于数据压缩。
+ +原始评分【4】→ AI重评【5】(重要树结构)
+二叉搜索树满足:左子树所有节点值 < 根节点值 < 右子树所有节点值。中序遍历BST可以得到有序序列。
+ +原始评分【3】→ AI重评【5】(图论基础)
+图由顶点(Vertex)和边(Edge)组成。图分为有向图和无向图。重要概念:度(与顶点相连的边数)、路径、环、连通性。
+ +原始评分【4】→ AI重评【6】(图论基础实现)
+
+// 邻接矩阵(适用于稠密图)
+int adj[505][505]; // adj[i][j] = 1 表示i到j有边
+adj[u][v] = 1;
+adj[v][u] = 1; // 无向图
+
+// 邻接表(适用于稀疏图,竞赛常用)
+vector<int> G[100005];
+G[u].push_back(v);
+G[v].push_back(u); // 无向图
+
+// 带权邻接表
+vector<pair<int,int>> G[100005]; // {目标节点, 权值}
+G[u].push_back({v, w});
+
+
+
+
+原始评分【1】→ AI重评【3】(基础理论重要) 原始评分【2】→ AI重评【3】(表达能力提升)
+算法是解决特定问题的一系列明确步骤。算法的五个基本特性:有穷性、确定性、可行性、输入、输出。评价算法的主要指标是时间复杂度和空间复杂度。
+| 时间复杂度 | 名称 | n=106时操作次数 | 可行性 |
|---|---|---|---|
| O(1) | 常数 | 1 | 极快 |
| O(log n) | 对数 | 20 | 极快 |
| O(n) | 线性 | 106 | 快 |
| O(n log n) | 线性对数 | 2×107 | 可行 |
| O(n2) | 平方 | 1012 | 不可行 |
| O(2n) | 指数 | 极大 | 不可行 |
原始评分【1】→ AI重评【3】(基础解题方法)
+枚举法(暴力法)是最基础的算法思想:遍历所有可能的解,逐一检验是否满足条件。
+
+// 示例:找出1~n中所有质数
+for (int i = 2; i <= n; i++) {
+ bool isPrime = true;
+ for (int j = 2; j * j <= i; j++) {
+ if (i % j == 0) { isPrime = false; break; }
+ }
+ if (isPrime) cout << i << " ";
+}
+
+
+原始评分【1】→ AI重评【6】(高频考点,实用性强)
+模拟法是按照题目描述的过程,用代码逐步模拟实现。这是CSP-J中出现频率最高的算法类型,几乎每年T1和T2都会考察。
+原始评分【3】→ AI重评【6】(高频且区分度高)
+贪心算法在每一步都选择当前最优的方案,期望最终得到全局最优解。贪心算法不一定能得到最优解,但对于某些特定问题(如活动选择、哈夫曼编码)可以证明其正确性。
+
+// 经典贪心:活动选择问题
+// 给定n个活动的开始和结束时间,选择最多不冲突的活动
+struct Activity {
+ int start, end;
+};
+bool cmp(Activity a, Activity b) {
+ return a.end < b.end; // 按结束时间排序
+}
+sort(act, act + n, cmp);
+int count = 1, lastEnd = act[0].end;
+for (int i = 1; i < n; i++) {
+ if (act[i].start >= lastEnd) {
+ count++;
+ lastEnd = act[i].end;
+ }
+}
+
+
+原始评分【3】→ AI重评【5】(动态规划基础)
+递推法通过已知的初始值和递推关系,逐步计算后续结果。递推是动态规划的基础。
++// 斐波那契数列 +int fib[105]; +fib[1] = 1; fib[2] = 1; +for (int i = 3; i <= n; i++) + fib[i] = fib[i-1] + fib[i-2]; ++ +
原始评分【4】→ AI重评【6】(重要思维方式)
+递归是函数调用自身的编程技巧。递归需要满足两个条件:基准情形(终止条件)和递归步骤(问题规模缩小)。
+
+// 汉诺塔问题
+void hanoi(int n, char from, char to, char aux) {
+ if (n == 1) {
+ cout << from << " -> " << to << endl;
+ return;
+ }
+ hanoi(n - 1, from, aux, to);
+ cout << from << " -> " << to << endl;
+ hanoi(n - 1, aux, to, from);
+}
+
+
+原始评分【4】→ AI重评【7】(高频且效率关键)
+二分法将搜索范围每次缩小一半,时间复杂度O(log n)。应用场景:有序数组查找、二分答案。
+
+// 二分查找
+int binarySearch(int a[], int n, int target) {
+ int left = 0, right = n - 1;
+ while (left <= right) {
+ int mid = left + (right - left) / 2;
+ if (a[mid] == target) return mid;
+ else if (a[mid] < target) left = mid + 1;
+ else right = mid - 1;
+ }
+ return -1; // 未找到
+}
+
+// 二分答案(竞赛高频模板)
+int left = 0, right = 1e9;
+while (left < right) {
+ int mid = (left + right) / 2;
+ if (check(mid)) right = mid; // check函数判断mid是否可行
+ else left = mid + 1;
+}
+// left就是答案
+
+原始评分【4】→ AI重评【7】(新增高效技巧)
+倍增法是一种以2的幂次为步长进行跳跃的算法思想。常用于求解LCA(最近公共祖先)、稀疏表(ST表)等问题。核心思想:将任意整数分解为若干2的幂次之和。
+ +原始评分【3】→ AI重评【5】(常用优化技巧)
+前缀和是一种预处理技巧,可以在O(1)时间内求出数组任意区间的和。
++// 一维前缀和 +int a[100005], prefix[100005]; +prefix[0] = 0; +for (int i = 1; i <= n; i++) + prefix[i] = prefix[i-1] + a[i]; + +// 查询区间[l, r]的和 +int sum = prefix[r] - prefix[l-1]; + +// 二维前缀和 +int s[505][505]; +for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j]; ++ +
原始评分【4】→ AI重评【6】(新增且实用)
+差分是前缀和的逆运算。差分数组可以在O(1)时间内对数组的一个区间进行加减操作。
+
+// 差分数组
+int diff[100005] = {0};
+
+// 对区间[l, r]的所有元素加val
+diff[l] += val;
+diff[r + 1] -= val;
+
+// 还原原数组
+for (int i = 1; i <= n; i++)
+ diff[i] += diff[i-1]; // diff[i]就是原数组a[i]的值
+
+
+原始评分【4】→ AI重评【5】(应用有限但难度较高)
+当数值超过long long的范围时,需要使用高精度运算(用数组模拟大数运算)。
+// 高精度加法
+string add(string a, string b) {
+ string result = "";
+ int carry = 0;
+ int i = a.size() - 1, j = b.size() - 1;
+ while (i >= 0 || j >= 0 || carry) {
+ int sum = carry;
+ if (i >= 0) sum += a[i--] - '0';
+ if (j >= 0) sum += b[j--] - '0';
+ result = char(sum % 10 + '0') + result;
+ carry = sum / 10;
+ }
+ return result;
+}
+
+
+原始评分【3】→ AI重评【5】(基础且频繁)
+ +| 算法 | 时间复杂度(平均) | 时间复杂度(最坏) | 空间复杂度 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 | O(n2) | O(n2) | O(1) | 稳定 |
| 选择排序 | O(n2) | O(n2) | O(1) | 不稳定 |
| 插入排序 | O(n2) | O(n2) | O(1) | 稳定 |
| 计数排序 | O(n+k) | O(n+k) | O(k) | 稳定 |
| sort(STL) | O(n log n) | O(n log n) | O(log n) | 不稳定 |
+// 冒泡排序
+for (int i = 0; i < n - 1; i++)
+ for (int j = 0; j < n - 1 - i; j++)
+ if (a[j] > a[j+1]) swap(a[j], a[j+1]);
+
+// 选择排序
+for (int i = 0; i < n - 1; i++) {
+ int minIdx = i;
+ for (int j = i + 1; j < n; j++)
+ if (a[j] < a[minIdx]) minIdx = j;
+ swap(a[i], a[minIdx]);
+}
+
+// 插入排序
+for (int i = 1; i < n; i++) {
+ int key = a[i], j = i - 1;
+ while (j >= 0 && a[j] > key) {
+ a[j+1] = a[j]; j--;
+ }
+ a[j+1] = key;
+}
+
+// 计数排序(适用于值域较小的情况)
+int cnt[100005] = {0};
+for (int i = 0; i < n; i++) cnt[a[i]]++;
+int idx = 0;
+for (int i = 0; i <= maxVal; i++)
+ while (cnt[i]--) a[idx++] = i;
+
+
+原始评分【5】→ AI重评【8】(高频关键算法)
+DFS沿着一条路径尽可能深入,直到无法继续时回溯。通常用递归或栈实现。
+
+// DFS模板 - 全排列
+int n, path[15];
+bool used[15];
+
+void dfs(int depth) {
+ if (depth == n) {
+ for (int i = 0; i < n; i++) cout << path[i] << " ";
+ cout << endl;
+ return;
+ }
+ for (int i = 1; i <= n; i++) {
+ if (!used[i]) {
+ used[i] = true;
+ path[depth] = i;
+ dfs(depth + 1);
+ used[i] = false; // 回溯
+ }
+ }
+}
+
+
+原始评分【5】→ AI重评【8】(高频关键算法)
+BFS逐层扩展搜索,使用队列实现。BFS可以找到最短路径(边权相同时)。
+
+// BFS模板 - 迷宫最短路
+int dx[] = {0, 0, 1, -1};
+int dy[] = {1, -1, 0, 0};
+int dist[505][505];
+bool vis[505][505];
+
+void bfs(int sx, int sy) {
+ queue<pair<int,int>> q;
+ q.push({sx, sy});
+ vis[sx][sy] = true;
+ dist[sx][sy] = 0;
+ 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] && grid[nx][ny] != '#') {
+ vis[nx][ny] = true;
+ dist[nx][ny] = dist[x][y] + 1;
+ q.push({nx, ny});
+ }
+ }
+ }
+}
+
+
+原始评分【4】→ AI重评【7】(图论核心算法) 原始评分【4】→ AI重评【7】(图论核心算法)
+
+// 图的DFS遍历
+bool vis[100005];
+void dfs(int u) {
+ vis[u] = true;
+ for (int v : G[u]) {
+ if (!vis[v]) dfs(v);
+ }
+}
+
+// 图的BFS遍历
+void bfs(int start) {
+ queue<int> q;
+ q.push(start);
+ vis[start] = true;
+ while (!q.empty()) {
+ int u = q.front(); q.pop();
+ for (int v : G[u]) {
+ if (!vis[v]) {
+ vis[v] = true;
+ q.push(v);
+ }
+ }
+ }
+}
+
+
+原始评分【5】→ AI重评【7】(常见应用,区分度高)
+泛洪算法用于填充连通区域,常用于统计连通块数量、图像填色等问题。
+
+// Flood Fill - 统计连通块数量
+int n, m, grid[505][505];
+bool vis[505][505];
+int dx[] = {0, 0, 1, -1};
+int dy[] = {1, -1, 0, 0};
+
+void floodFill(int x, int y, int color) {
+ vis[x][y] = true;
+ 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] && grid[nx][ny] == color) {
+ floodFill(nx, ny, color);
+ }
+ }
+}
+
+// 统计连通块数量
+int count = 0;
+for (int i = 0; i < n; i++)
+ for (int j = 0; j < m; j++)
+ if (!vis[i][j]) {
+ floodFill(i, j, grid[i][j]);
+ count++;
+ }
+
+
+原始评分【4】→ AI重评【9】(拉开差距关键)
+动态规划(DP)是解决最优化问题的核心算法思想。DP的核心要素:
+| 要素 | 说明 |
|---|---|
| 最优子结构 | 问题的最优解包含子问题的最优解 |
| 重叠子问题 | 不同的决策路径会产生相同的子问题 |
| 状态定义 | 用数组dp[i]表示到第i个阶段的最优解 |
| 状态转移方程 | 描述状态之间的递推关系 |
| 边界条件 | 初始状态的值 |
原始评分【4】→ AI重评【9】(基础DP,频繁考)
+
+// 经典问题:最长递增子序列(LIS)
+// dp[i] = 以a[i]结尾的最长递增子序列长度
+int dp[100005];
+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);
+ }
+}
+int ans = *max_element(dp, dp + n);
+
+// 经典问题:爬楼梯
+// dp[i] = 到达第i级台阶的方案数
+dp[1] = 1; dp[2] = 2;
+for (int i = 3; i <= n; i++)
+ dp[i] = dp[i-1] + dp[i-2];
+
+
+原始评分【5】→ AI重评【9】(高频难点)
+
+// 0-1背包问题
+// n个物品,背包容量W,第i个物品重量w[i],价值v[i]
+// dp[j] = 容量为j时的最大价值
+int dp[100005] = {0};
+for (int i = 1; i <= n; i++)
+ for (int j = W; j >= w[i]; j--) // 逆序遍历!
+ dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
+cout << dp[W];
+
+// 完全背包问题(每种物品可以选无限次)
+for (int i = 1; i <= n; i++)
+ for (int j = w[i]; j <= W; j++) // 正序遍历!
+ dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
+
+
+原始评分【5】→ AI重评【9】(高频难点)
+
+// 区间DP模板:石子合并
+// dp[i][j] = 合并第i堆到第j堆石子的最小代价
+int dp[505][505], prefix[505];
+memset(dp, 0x3f, sizeof(dp));
+for (int i = 1; i <= n; i++) dp[i][i] = 0;
+
+for (int len = 2; len <= n; len++) { // 枚举区间长度
+ for (int i = 1; i + len - 1 <= n; i++) { // 枚举左端点
+ int j = i + len - 1; // 右端点
+ for (int k = i; k < j; k++) { // 枚举分割点
+ dp[i][j] = min(dp[i][j],
+ dp[i][k] + dp[k+1][j] + prefix[j] - prefix[i-1]);
+ }
+ }
+}
+
+
+
+
+原始评分【1】→ AI重评【2】(基础数学知识)
+了解自然数、整数、有理数、实数的概念及其四则运算。在计算机中,整数和浮点数的表示方式不同,需要注意精度问题。
+ +原始评分【1】→ AI重评【3】(竞赛常用基础)
+
+// 十进制转其他进制
+void toBase(int n, int base) {
+ if (n == 0) return;
+ toBase(n / base, base);
+ cout << n % base;
+}
+
+// 其他进制转十进制
+int toDecimal(string s, int base) {
+ int result = 0;
+ for (char c : s) {
+ result = result * base + (c - '0');
+ }
+ return result;
+}
+
+
+原始评分【1】→ AI重评【2】(基础数学) 原始评分【1】→ AI重评【2】(基础数学)
+掌握初中阶段的代数知识(一元一次方程、一元二次方程、不等式等)和几何知识(三角形、四边形、圆的面积和周长等)。CSP-J 2023年T3就考察了一元二次方程的求解。
+ +原始评分【3】→ AI重评【5】(数学基础,频繁考)
+
+// 判断质数
+bool isPrime(int n) {
+ if (n < 2) return false;
+ for (int i = 2; i * i <= n; i++)
+ if (n % i == 0) return false;
+ return true;
+}
+
+// 分解质因数
+void factorize(int n) {
+ for (int i = 2; i * i <= n; i++) {
+ while (n % i == 0) {
+ cout << i << " ";
+ n /= i;
+ }
+ }
+ if (n > 1) cout << n;
+}
+
+
+原始评分【3】→ AI重评【4】(数学技巧)
+上取整:ceil(a/b) = (a + b - 1) / b(整数除法技巧)。下取整:C++中整数除法默认下取整。
原始评分【3】→ AI重评【6】(高频数学技巧)
+模运算的基本性质:(a + b) % m = ((a % m) + (b % m)) % m,乘法同理。竞赛中常见"答案对109+7取模"。
+const int MOD = 1e9 + 7;
+long long ans = 0;
+for (int i = 0; i < n; i++) {
+ ans = (ans + a[i]) % MOD;
+}
+
+
+原始评分【3】→ AI重评【5】(数学基础)
+任何大于1的正整数都可以唯一地分解为若干质数的乘积:n = p1a1 × p2a2 × ... × pkak。
+ +原始评分【3】→ AI重评【6】(高频数学算法)
+
+// 最大公约数(GCD)
+int gcd(int a, int b) {
+ return b == 0 ? a : gcd(b, a % b);
+}
+
+// 最小公倍数(LCM)
+int lcm(int a, int b) {
+ return a / gcd(a, b) * b; // 先除后乘防溢出
+}
+
+// C++14起可直接使用 __gcd(a, b)
+
+
+原始评分【4】→ AI重评【7】(高频数学算法)
+
+// 埃氏筛法 O(n log log n)
+bool notPrime[10000005];
+void sieve(int n) {
+ notPrime[0] = notPrime[1] = true;
+ for (int i = 2; i * i <= n; i++) {
+ if (!notPrime[i]) {
+ for (int j = i * i; j <= n; j += i)
+ notPrime[j] = true;
+ }
+ }
+}
+
+// 线性筛(欧拉筛)O(n)
+int primes[1000005], cnt = 0;
+bool notPrime2[10000005];
+void linearSieve(int n) {
+ for (int i = 2; i <= n; i++) {
+ if (!notPrime2[i]) primes[cnt++] = i;
+ for (int j = 0; j < cnt && i * primes[j] <= n; j++) {
+ notPrime2[i * primes[j]] = true;
+ if (i % primes[j] == 0) break;
+ }
+ }
+}
+
+
+原始评分【2】→ AI重评【3】(基础数学概念) 原始评分【2】→ AI重评【3】(组合数学基础) 原始评分【2】→ AI重评【3】(组合数学基础)
+加法原理:完成一件事有n类方法,第i类有ai种,总方法数为 Σai。乘法原理:完成一件事需要n个步骤,第i步有ai种方法,总方法数为 Πai。
+ +原始评分【4】→ AI重评【5】(组合数学重要) 原始评分【4】→ AI重评【5】(组合数学重要)
+排列:从n个元素中取r个排列,P(n,r) = n!/(n-r)!。组合:从n个元素中取r个组合,C(n,r) = n!/(r!(n-r)!)。
+
+// 计算组合数 C(n, r)
+long long C[1005][1005];
+void initC(int maxn) {
+ for (int i = 0; i <= maxn; i++) {
+ C[i][0] = 1;
+ for (int j = 1; j <= i; j++)
+ C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
+ }
+}
+
+
+难度评级【4】
+杨辉三角的第n行第k个数就是组合数C(n,k)。杨辉三角的递推关系:C(n,k) = C(n-1,k-1) + C(n-1,k)。
+ +原始评分【2】→ AI重评【3】(字符串处理基础)
+| 字符 | ASCII码 | 常用关系 |
|---|---|---|
| '0'~'9' | 48~57 | 数字字符转数字:c - '0' |
| 'A'~'Z' | 65~90 | 大写转小写:c + 32 或 c + 'a' - 'A' |
| 'a'~'z' | 97~122 | 小写转大写:c - 32 或 c - 'a' + 'A' |
以下表格列出了所有经过AI模型重新评估后评分发生变化的知识点(黄色高亮标记)。评分基于全网深度调研数据,综合考虑考试重要性、学习难度、区分度和实用性四个维度。
+ +| 编号 | 知识点 | 原始评分 | AI重评分 | 变化 | 评分理由 |
|---|---|---|---|---|---|
| 1 | 计算机的基本构成 | 【1】 | 【2】 | +1 | 基础重要,竞赛环境必备 |
| 2 | 操作系统基本概念及常见操作 | 【1】 | 【2】 | +1 | 环境操作基础,实用性提升 |
| 3 | 计算机网络和Internet基本概念 | 【1】 | 【1】 | - | 竞赛中应用较少 |
| 4 | 计算机的历史和常见用途 | 【1】 | 【1】 | - | 理论性强,实用性低 |
| 5 | NOI相关活动的历史与规则 | 【1】 | 【1】 | - | 非技术核心内容 |
| 6 | 位、字节与字 | 【1】 | 【3】 | +2 | 位运算基础,竞赛常用 |
| 7 | 程序设计语言及编译运行基本概念 | 【1】 | 【2】 | +1 | 理解编译流程重要 |
| 8 | 文件/目录的图形界面操作 | 【1】 | 【1】 | - | 竞赛中应用少 |
| 9 | Windows/Linux集成开发环境使用 | 【1】 | 【2】 | +1 | 开发环境熟悉度重要 |
| 10 | 编译命令g++的基本使用 | 【1】 | 【3】 | +2 | 编译命令基础,实用性强 |
| 11 | 标识符、关键字、常量、变量、表达式 | 【1】 | 【3】 | +2 | 编程基础,必备知识 |
| 12 | 常量与变量的命名、定义及作用 | 【1】 | 【3】 | +2 | 基础语法,重要性提升 |
| 13 | 头文件与名字空间 | 【2】 | 【3】 | +1 | 代码组织关键 |
| 14 | 编辑、编译、解释、调试概念 | 【2】 | 【3】 | +1 | 调试能力重要 |
| 15 | 基本数据类型(int,long long,float,double,char,bool) | 【1】 | 【3】 | +2 | 类型理解基础 |
| 16 | 输入输出语句(cin/cout/scanf/printf) | 【2】 | 【3】 | +1 | IO基础,频繁使用 |
| 17 | 条件语句(if/switch) | 【2】 | 【3】 | +1 | 控制流基础 |
| 18 | 循环语句(for/while/do while) | 【2】 | 【3】 | +1 | 循环结构核心 |
| 19 | 多层循环语句 | 【3】 | 【4】 | +1 | 复杂度提升,常见考点 |
| 20 | 算术/关系/逻辑运算 | 【1】 | 【3】 | +2 | 运算基础,频繁使用 |
| 21 | 位运算 | 【2】 | 【5】 | +3 | 高频考点,难度较大 |
| 22 | 数学库常用函数 | 【3】 | 【4】 | +1 | 数学思维增强 |
| 23 | 顺序/分支/循环结构 | 【1】 | 【3】 | +2 | 基础结构,重要性提升 |
| 24 | 模块化程序设计与流程图 | 【2】 | 【3】 | +1 | 代码组织与设计 |
| 25 | 数组与数组下标 | 【1】 | 【4】 | +3 | 基础数据结构,应用广 |
| 26 | 二维数组与多维数组 | 【3】 | 【4】 | +1 | 常见数据结构 |
| 27 | 字符数组与string类 | 【2】 | 【4】 | +2 | 字符串处理基础 |
| 28 | 函数定义与调用、递归函数 | 【2】 | 【5】 | +3 | 递归难点,重要考点 |
| 29 | 传值与传引用参数 | 【3】 | 【4】 | +1 | 参数传递细节重要 |
| 30 | 结构体与联合体 | 【3】 | 【4】 | +1 | 数据组织关键 |
| 31 | 指针与引用 | 【4】 | 【5】 | +1 | 核心难点,区分度高 |
| 32 | 文件读写 | 【2】 | 【3】 | +1 | 竞赛中偶尔应用 |
| 33 | STL常用函数(min/max/swap/sort) | 【3】 | 【5】 | +2 | 高频实用,效率提升 |
| 34 | STL容器(stack/queue/list/vector) | 【4】 | 【6】 | +2 | 竞赛必备,应用广泛 |
| 35 | 链表(单/双向/循环) | 【3】 | 【4】 | +1 | 数据结构基础 |
| 36 | 栈 | 【3】 | 【5】 | +2 | 高频考点,应用广 |
| 37 | 队列 | 【3】 | 【5】 | +2 | 高频考点,应用广 |
| 38 | 树的定义与基本概念 | 【3】 | 【5】 | +2 | 基础数据结构 |
| 39 | 二叉树定义与基本性质 | 【3】 | 【5】 | +2 | 基础树结构 |
| 40 | 树/二叉树的表示与存储 | 【4】 | 【6】 | +2 | 存储实现关键 |
| 41 | 二叉树的遍历(前序/中序/后序) | 【4】 | 【6】 | +2 | 遍历是基础技能 |
| 42 | 完全二叉树定义、性质与数组表示 | 【4】 | 【6】 | +2 | 重要树结构 |
| 43 | 哈夫曼树与哈夫曼编码 | 【4】 | 【5】 | +1 | 经典算法,应用有限 |
| 44 | 二叉搜索树 | 【4】 | 【5】 | +1 | 重要树结构 |
| 45 | 图的定义与相关概念 | 【3】 | 【5】 | +2 | 图论基础 |
| 46 | 图的存储(邻接矩阵/邻接表) | 【4】 | 【6】 | +2 | 图论基础实现 |
| 47 | 算法概念 | 【1】 | 【3】 | +2 | 基础理论重要 |
| 48 | 算法描述(自然语言/流程图/伪代码) | 【2】 | 【3】 | +1 | 表达能力提升 |
| 49 | 枚举法 | 【1】 | 【3】 | +2 | 基础解题方法 |
| 50 | 模拟法 | 【1】 | 【6】 | +5 | 高频考点,实用性强 |
| 51 | 贪心法 | 【3】 | 【6】 | +3 | 高频且区分度高 |
| 52 | 递推法 | 【3】 | 【5】 | +2 | 动态规划基础 |
| 53 | 递归法 | 【4】 | 【6】 | +2 | 重要思维方式 |
| 54 | 二分法 | 【4】 | 【7】 | +3 | 高频且效率关键 |
| 55 | 倍增法 | 【4】 | 【7】 | +3 | 新增高效技巧 |
| 56 | 前缀和 | 【3】 | 【5】 | +2 | 常用优化技巧 |
| 57 | 差分 | 【4】 | 【6】 | +2 | 新增且实用 |
| 58 | 高精度运算 | 【4】 | 【5】 | +1 | 应用有限但难度较高 |
| 59 | 排序基本概念 | 【3】 | 【5】 | +2 | 基础且频繁 |
| 60 | 冒泡排序 | 【3】 | 【3】 | - | 基础教学用 |
| 61 | 选择排序 | 【3】 | 【3】 | - | 基础教学用 |
| 62 | 插入排序 | 【3】 | 【3】 | - | 基础教学用 |
| 63 | 计数排序 | 【3】 | 【4】 | +1 | 常用优化排序 |
| 64 | 深度优先搜索(DFS) | 【5】 | 【8】 | +3 | 高频关键算法 |
| 65 | 广度优先搜索(BFS) | 【5】 | 【8】 | +3 | 高频关键算法 |
| 66 | 图的深度优先遍历 | 【4】 | 【7】 | +3 | 图论核心算法 |
| 67 | 图的广度优先遍历 | 【4】 | 【7】 | +3 | 图论核心算法 |
| 68 | 泛洪算法(Flood Fill) | 【5】 | 【7】 | +2 | 常见应用,区分度高 |
| 69 | 动态规划基本思路 | 【4】 | 【9】 | +5 | 拉开差距关键 |
| 70 | 简单一维动态规划 | 【4】 | 【9】 | +5 | 基础DP,频繁考 |
| 71 | 简单背包类型动态规划 | 【5】 | 【9】 | +4 | 高频难点 |
| 72 | 简单区间类型动态规划 | 【5】 | 【9】 | +4 | 高频难点 |
| 73 | 自然数/整数/有理数/实数及运算 | 【1】 | 【2】 | +1 | 基础数学知识 |
| 74 | 进制与进制转换 | 【1】 | 【3】 | +2 | 竞赛常用基础 |
| 75 | 代数(初中部分) | 【1】 | 【2】 | +1 | 基础数学 |
| 76 | 几何(初中部分) | 【1】 | 【2】 | +1 | 基础数学 |
| 77 | 整除/因数/倍数/质数/合数 | 【3】 | 【5】 | +2 | 数学基础,频繁考 |
| 78 | 取整 | 【3】 | 【4】 | +1 | 数学技巧 |
| 79 | 模运算与取余 | 【3】 | 【6】 | +3 | 高频数学技巧 |
| 80 | 整数唯一分解定理 | 【3】 | 【5】 | +2 | 数学基础 |
| 81 | 辗转相除法(欧几里得算法) | 【3】 | 【6】 | +3 | 高频数学算法 |
| 82 | 素数筛法(埃氏筛/线性筛) | 【4】 | 【7】 | +3 | 高频数学算法 |
| 83 | 集合 | 【2】 | 【3】 | +1 | 基础数学概念 |
| 84 | 加法原理 | 【2】 | 【3】 | +1 | 组合数学基础 |
| 85 | 乘法原理 | 【2】 | 【3】 | +1 | 组合数学基础 |
| 86 | 排列 | 【4】 | 【5】 | +1 | 组合数学重要 |
| 87 | 组合 | 【4】 | 【5】 | +1 | 组合数学重要 |
| 88 | 杨辉三角 | 【4】 | 【4】 | - | 基础数学工具 |
| 89 | ASCII码 | 【2】 | 【3】 | +1 | 字符串处理基础 |
+— 文档生成日期:2026年3月14日 | 基于 NOI 大纲(2025年修订版)— +
+ + + diff --git a/NOI_Beginner_Guide_2025.pdf b/NOI_Beginner_Guide_2025.pdf new file mode 100644 index 0000000..2b96ed0 Binary files /dev/null and b/NOI_Beginner_Guide_2025.pdf differ diff --git a/README.md b/README.md index 02dae2e..80f5ca9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,46 @@ -# noi-beginner-guide +# NOI 入门级完整学习手册 -NOI 入门级完整学习手册(2025年修订版)- 含全网调研AI重评分、详细知识点讲解与代码示例 \ No newline at end of file +基于 **NOI 大纲(2025年修订版)**,包含全网深度调研AI重评分、详细知识点讲解与代码示例。 + +## 文档概述 + +本仓库提供 NOI(全国青少年信息学奥林匹克竞赛)入门级的完整学习资料,覆盖 CSP-J 认证所需的全部知识点。 + +## 内容结构 + +| 章节 | 内容 | 知识点数量 | +|------|------|----------| +| 第一章 | 基础知识与编程环境 | 12 | +| 第二章 | C++程序设计 | 22 | +| 第三章 | 数据结构 | 13 | +| 第四章 | 算法 | 25 | +| 第五章 | 数学与其他 | 17 | +| 附录 | 评分变化汇总表 | 89 | + +## 特色功能 + +**AI 重评分系统**:基于全网深度调研(CSP-J 历年真题考点分析、竞赛趋势报告),使用 AI 模型对每个知识点的难度和重要性进行重新评估。评分变化的知识点以黄色背景高亮标记,便于识别重点。 + +评分维度包括:考试重要性(考频)、学习难度、区分度(拉开差距能力)、实用性(竞赛应用广度),综合评分 1-10 分。 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `NOI_Beginner_Guide_2025.pdf` | 完整学习手册 PDF 版本(45页) | +| `NOI_Beginner_Guide_2025.html` | 完整学习手册 HTML 源文件 | +| `ai_scores.json` | AI 模型评分数据(JSON 格式) | +| `ai_scoring.py` | AI 评分脚本 | +| `generate_detailed_doc.py` | 文档生成脚本 | +| `research_findings.txt` | 全网调研数据 | + +## 数据来源 + +1. [NOI 大纲(2025年修订版)](https://www.noi.cn/xw/2025-04-18/841584.shtml) +2. CSP-J 历年复赛真题考察内容(2010-2023)考点分析 +3. CSP-J/S 2025 入门级题目知识构成分析报告 +4. AI 模型评分(gpt-4.1-mini) + +## 许可 + +本文档仅供学习参考使用。NOI 大纲版权归中国计算机学会(CCF)所有。 diff --git a/ai_scores.json b/ai_scores.json new file mode 100644 index 0000000..54351b0 --- /dev/null +++ b/ai_scores.json @@ -0,0 +1,714 @@ +[ + { + "id": 1, + "name": "计算机的基本构成", + "original_score": 1, + "new_score": 2, + "changed": true, + "reason": "基础重要,竞赛环境必备" + }, + { + "id": 2, + "name": "操作系统基本概念及常见操作", + "original_score": 1, + "new_score": 2, + "changed": true, + "reason": "环境操作基础,实用性提升" + }, + { + "id": 3, + "name": "计算机网络和Internet基本概念", + "original_score": 1, + "new_score": 1, + "changed": false, + "reason": "竞赛中应用较少" + }, + { + "id": 4, + "name": "计算机的历史和常见用途", + "original_score": 1, + "new_score": 1, + "changed": false, + "reason": "理论性强,实用性低" + }, + { + "id": 5, + "name": "NOI相关活动的历史与规则", + "original_score": 1, + "new_score": 1, + "changed": false, + "reason": "非技术核心内容" + }, + { + "id": 6, + "name": "位、字节与字", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "位运算基础,竞赛常用" + }, + { + "id": 7, + "name": "程序设计语言及编译运行基本概念", + "original_score": 1, + "new_score": 2, + "changed": true, + "reason": "理解编译流程重要" + }, + { + "id": 8, + "name": "文件/目录的图形界面操作", + "original_score": 1, + "new_score": 1, + "changed": false, + "reason": "竞赛中应用少" + }, + { + "id": 9, + "name": "Windows/Linux集成开发环境使用", + "original_score": 1, + "new_score": 2, + "changed": true, + "reason": "开发环境熟悉度重要" + }, + { + "id": 10, + "name": "编译命令g++的基本使用", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "编译命令基础,实用性强" + }, + { + "id": 11, + "name": "标识符、关键字、常量、变量、表达式", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "编程基础,必备知识" + }, + { + "id": 12, + "name": "常量与变量的命名、定义及作用", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "基础语法,重要性提升" + }, + { + "id": 13, + "name": "头文件与名字空间", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "代码组织关键" + }, + { + "id": 14, + "name": "编辑、编译、解释、调试概念", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "调试能力重要" + }, + { + "id": 15, + "name": "基本数据类型(int,long long,float,double,char,bool)", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "类型理解基础" + }, + { + "id": 16, + "name": "输入输出语句(cin/cout/scanf/printf)", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "IO基础,频繁使用" + }, + { + "id": 17, + "name": "条件语句(if/switch)", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "控制流基础" + }, + { + "id": 18, + "name": "循环语句(for/while/do while)", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "循环结构核心" + }, + { + "id": 19, + "name": "多层循环语句", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "复杂度提升,常见考点" + }, + { + "id": 20, + "name": "算术/关系/逻辑运算", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "运算基础,频繁使用" + }, + { + "id": 21, + "name": "位运算", + "original_score": 2, + "new_score": 5, + "changed": true, + "reason": "高频考点,难度较大" + }, + { + "id": 22, + "name": "数学库常用函数", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "数学思维增强" + }, + { + "id": 23, + "name": "顺序/分支/循环结构", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "基础结构,重要性提升" + }, + { + "id": 24, + "name": "模块化程序设计与流程图", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "代码组织与设计" + }, + { + "id": 25, + "name": "数组与数组下标", + "original_score": 1, + "new_score": 4, + "changed": true, + "reason": "基础数据结构,应用广" + }, + { + "id": 26, + "name": "二维数组与多维数组", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "常见数据结构" + }, + { + "id": 27, + "name": "字符数组与string类", + "original_score": 2, + "new_score": 4, + "changed": true, + "reason": "字符串处理基础" + }, + { + "id": 28, + "name": "函数定义与调用、递归函数", + "original_score": 2, + "new_score": 5, + "changed": true, + "reason": "递归难点,重要考点" + }, + { + "id": 29, + "name": "传值与传引用参数", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "参数传递细节重要" + }, + { + "id": 30, + "name": "结构体与联合体", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "数据组织关键" + }, + { + "id": 31, + "name": "指针与引用", + "original_score": 4, + "new_score": 5, + "changed": true, + "reason": "核心难点,区分度高" + }, + { + "id": 32, + "name": "文件读写", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "竞赛中偶尔应用" + }, + { + "id": 33, + "name": "STL常用函数(min/max/swap/sort)", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "高频实用,效率提升" + }, + { + "id": 34, + "name": "STL容器(stack/queue/list/vector)", + "original_score": 4, + "new_score": 6, + "changed": true, + "reason": "竞赛必备,应用广泛" + }, + { + "id": 35, + "name": "链表(单/双向/循环)", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "数据结构基础" + }, + { + "id": 36, + "name": "栈", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "高频考点,应用广" + }, + { + "id": 37, + "name": "队列", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "高频考点,应用广" + }, + { + "id": 38, + "name": "树的定义与基本概念", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "基础数据结构" + }, + { + "id": 39, + "name": "二叉树定义与基本性质", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "基础树结构" + }, + { + "id": 40, + "name": "树/二叉树的表示与存储", + "original_score": 4, + "new_score": 6, + "changed": true, + "reason": "存储实现关键" + }, + { + "id": 41, + "name": "二叉树的遍历(前序/中序/后序)", + "original_score": 4, + "new_score": 6, + "changed": true, + "reason": "遍历是基础技能" + }, + { + "id": 42, + "name": "完全二叉树定义、性质与数组表示", + "original_score": 4, + "new_score": 6, + "changed": true, + "reason": "重要树结构" + }, + { + "id": 43, + "name": "哈夫曼树与哈夫曼编码", + "original_score": 4, + "new_score": 5, + "changed": true, + "reason": "经典算法,应用有限" + }, + { + "id": 44, + "name": "二叉搜索树", + "original_score": 4, + "new_score": 5, + "changed": true, + "reason": "重要树结构" + }, + { + "id": 45, + "name": "图的定义与相关概念", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "图论基础" + }, + { + "id": 46, + "name": "图的存储(邻接矩阵/邻接表)", + "original_score": 4, + "new_score": 6, + "changed": true, + "reason": "图论基础实现" + }, + { + "id": 47, + "name": "算法概念", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "基础理论重要" + }, + { + "id": 48, + "name": "算法描述(自然语言/流程图/伪代码)", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "表达能力提升" + }, + { + "id": 49, + "name": "枚举法", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "基础解题方法" + }, + { + "id": 50, + "name": "模拟法", + "original_score": 1, + "new_score": 6, + "changed": true, + "reason": "高频考点,实用性强" + }, + { + "id": 51, + "name": "贪心法", + "original_score": 3, + "new_score": 6, + "changed": true, + "reason": "高频且区分度高" + }, + { + "id": 52, + "name": "递推法", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "动态规划基础" + }, + { + "id": 53, + "name": "递归法", + "original_score": 4, + "new_score": 6, + "changed": true, + "reason": "重要思维方式" + }, + { + "id": 54, + "name": "二分法", + "original_score": 4, + "new_score": 7, + "changed": true, + "reason": "高频且效率关键" + }, + { + "id": 55, + "name": "倍增法", + "original_score": 4, + "new_score": 7, + "changed": true, + "reason": "新增高效技巧" + }, + { + "id": 56, + "name": "前缀和", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "常用优化技巧" + }, + { + "id": 57, + "name": "差分", + "original_score": 4, + "new_score": 6, + "changed": true, + "reason": "新增且实用" + }, + { + "id": 58, + "name": "高精度运算", + "original_score": 4, + "new_score": 5, + "changed": true, + "reason": "应用有限但难度较高" + }, + { + "id": 59, + "name": "排序基本概念", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "基础且频繁" + }, + { + "id": 60, + "name": "冒泡排序", + "original_score": 3, + "new_score": 3, + "changed": false, + "reason": "基础教学用" + }, + { + "id": 61, + "name": "选择排序", + "original_score": 3, + "new_score": 3, + "changed": false, + "reason": "基础教学用" + }, + { + "id": 62, + "name": "插入排序", + "original_score": 3, + "new_score": 3, + "changed": false, + "reason": "基础教学用" + }, + { + "id": 63, + "name": "计数排序", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "常用优化排序" + }, + { + "id": 64, + "name": "深度优先搜索(DFS)", + "original_score": 5, + "new_score": 8, + "changed": true, + "reason": "高频关键算法" + }, + { + "id": 65, + "name": "广度优先搜索(BFS)", + "original_score": 5, + "new_score": 8, + "changed": true, + "reason": "高频关键算法" + }, + { + "id": 66, + "name": "图的深度优先遍历", + "original_score": 4, + "new_score": 7, + "changed": true, + "reason": "图论核心算法" + }, + { + "id": 67, + "name": "图的广度优先遍历", + "original_score": 4, + "new_score": 7, + "changed": true, + "reason": "图论核心算法" + }, + { + "id": 68, + "name": "泛洪算法(Flood Fill)", + "original_score": 5, + "new_score": 7, + "changed": true, + "reason": "常见应用,区分度高" + }, + { + "id": 69, + "name": "动态规划基本思路", + "original_score": 4, + "new_score": 9, + "changed": true, + "reason": "拉开差距关键" + }, + { + "id": 70, + "name": "简单一维动态规划", + "original_score": 4, + "new_score": 9, + "changed": true, + "reason": "基础DP,频繁考" + }, + { + "id": 71, + "name": "简单背包类型动态规划", + "original_score": 5, + "new_score": 9, + "changed": true, + "reason": "高频难点" + }, + { + "id": 72, + "name": "简单区间类型动态规划", + "original_score": 5, + "new_score": 9, + "changed": true, + "reason": "高频难点" + }, + { + "id": 73, + "name": "自然数/整数/有理数/实数及运算", + "original_score": 1, + "new_score": 2, + "changed": true, + "reason": "基础数学知识" + }, + { + "id": 74, + "name": "进制与进制转换", + "original_score": 1, + "new_score": 3, + "changed": true, + "reason": "竞赛常用基础" + }, + { + "id": 75, + "name": "代数(初中部分)", + "original_score": 1, + "new_score": 2, + "changed": true, + "reason": "基础数学" + }, + { + "id": 76, + "name": "几何(初中部分)", + "original_score": 1, + "new_score": 2, + "changed": true, + "reason": "基础数学" + }, + { + "id": 77, + "name": "整除/因数/倍数/质数/合数", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "数学基础,频繁考" + }, + { + "id": 78, + "name": "取整", + "original_score": 3, + "new_score": 4, + "changed": true, + "reason": "数学技巧" + }, + { + "id": 79, + "name": "模运算与取余", + "original_score": 3, + "new_score": 6, + "changed": true, + "reason": "高频数学技巧" + }, + { + "id": 80, + "name": "整数唯一分解定理", + "original_score": 3, + "new_score": 5, + "changed": true, + "reason": "数学基础" + }, + { + "id": 81, + "name": "辗转相除法(欧几里得算法)", + "original_score": 3, + "new_score": 6, + "changed": true, + "reason": "高频数学算法" + }, + { + "id": 82, + "name": "素数筛法(埃氏筛/线性筛)", + "original_score": 4, + "new_score": 7, + "changed": true, + "reason": "高频数学算法" + }, + { + "id": 83, + "name": "集合", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "基础数学概念" + }, + { + "id": 84, + "name": "加法原理", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "组合数学基础" + }, + { + "id": 85, + "name": "乘法原理", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "组合数学基础" + }, + { + "id": 86, + "name": "排列", + "original_score": 4, + "new_score": 5, + "changed": true, + "reason": "组合数学重要" + }, + { + "id": 87, + "name": "组合", + "original_score": 4, + "new_score": 5, + "changed": true, + "reason": "组合数学重要" + }, + { + "id": 88, + "name": "杨辉三角", + "original_score": 4, + "new_score": 4, + "changed": false, + "reason": "基础数学工具" + }, + { + "id": 89, + "name": "ASCII码", + "original_score": 2, + "new_score": 3, + "changed": true, + "reason": "字符串处理基础" + } +] \ No newline at end of file diff --git a/ai_scoring.py b/ai_scoring.py new file mode 100644 index 0000000..81b768c --- /dev/null +++ b/ai_scoring.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +""" +调用AI模型对NOI入门级知识点进行重新评分 +基于全网调研数据(CSP-J历年真题考频、难度趋势、2025大纲修订) +""" +import json +from openai import OpenAI + +client = OpenAI() + +# 入门级所有知识点及其原始评分 +knowledge_points = """ +以下是NOI大纲(2025年修订版)入门级的所有知识点及其原始难度评级(1-5分)。 +请你作为NOI竞赛专家,结合以下调研数据,对每个知识点重新评分。 + +调研数据: +1. CSP-J历年真题(2010-2025)考点频率分析: + - T1高频:模拟法、整数拆分/数位分离、字符串基础、数学 + - T2高频:模拟、贪心、排序、队列、二分、时间复杂度优化 + - T3高频:动态规划(线性DP/背包DP)、数据结构(栈/队列/树)、BFS/DFS、字符串大模拟 + - T4高频:DP/图论/树型数据结构、最短路、拓扑排序 +2. 近年趋势:难度持续上升,时间复杂度优化成标配,数学思维考察增多 +3. DP是CSP-J拉开差距的关键考点 +4. 2025年大纲新增了倍增法、差分等知识点 + +评分维度(综合以下4个维度给出1-10分的综合评分): +- 考试重要性(考频高=分高) +- 学习难度(越难=分越高) +- 区分度(能拉开差距=分高) +- 实用性(在实际竞赛中的应用广度) + +请对以下每个知识点给出: +1. 新的综合评分(1-10分) +2. 是否与原始评分不同(标记changed=true/false) +3. 简短的评分理由(20字以内) + +知识点列表(格式:编号 | 知识点名称 | 原始评级): + +=== 2.1.1 基础知识与编程环境 === +1 | 计算机的基本构成 | 1 +2 | 操作系统基本概念及常见操作 | 1 +3 | 计算机网络和Internet基本概念 | 1 +4 | 计算机的历史和常见用途 | 1 +5 | NOI相关活动的历史与规则 | 1 +6 | 位、字节与字 | 1 +7 | 程序设计语言及编译运行基本概念 | 1 +8 | 文件/目录的图形界面操作 | 1 +9 | Windows/Linux集成开发环境使用 | 1 +10 | 编译命令g++的基本使用 | 1 + +=== 2.1.2 C++程序设计 === +11 | 标识符、关键字、常量、变量、表达式 | 1 +12 | 常量与变量的命名、定义及作用 | 1 +13 | 头文件与名字空间 | 2 +14 | 编辑、编译、解释、调试概念 | 2 +15 | 基本数据类型(int,long long,float,double,char,bool) | 1 +16 | 输入输出语句(cin/cout/scanf/printf) | 2 +17 | 条件语句(if/switch) | 2 +18 | 循环语句(for/while/do while) | 2 +19 | 多层循环语句 | 3 +20 | 算术/关系/逻辑运算 | 1 +21 | 位运算 | 2 +22 | 数学库常用函数 | 3 +23 | 顺序/分支/循环结构 | 1 +24 | 模块化程序设计与流程图 | 2 +25 | 数组与数组下标 | 1 +26 | 二维数组与多维数组 | 3 +27 | 字符数组与string类 | 2 +28 | 函数定义与调用、递归函数 | 2 +29 | 传值与传引用参数 | 3 +30 | 结构体与联合体 | 3 +31 | 指针与引用 | 4 +32 | 文件读写 | 2 +33 | STL常用函数(min/max/swap/sort) | 3 +34 | STL容器(stack/queue/list/vector) | 4 + +=== 2.1.3 数据结构 === +35 | 链表(单/双向/循环) | 3 +36 | 栈 | 3 +37 | 队列 | 3 +38 | 树的定义与基本概念 | 3 +39 | 二叉树定义与基本性质 | 3 +40 | 树/二叉树的表示与存储 | 4 +41 | 二叉树的遍历(前序/中序/后序) | 4 +42 | 完全二叉树定义、性质与数组表示 | 4 +43 | 哈夫曼树与哈夫曼编码 | 4 +44 | 二叉搜索树 | 4 +45 | 图的定义与相关概念 | 3 +46 | 图的存储(邻接矩阵/邻接表) | 4 + +=== 2.1.4 算法 === +47 | 算法概念 | 1 +48 | 算法描述(自然语言/流程图/伪代码) | 2 +49 | 枚举法 | 1 +50 | 模拟法 | 1 +51 | 贪心法 | 3 +52 | 递推法 | 3 +53 | 递归法 | 4 +54 | 二分法 | 4 +55 | 倍增法 | 4 +56 | 前缀和 | 3 +57 | 差分 | 4 +58 | 高精度运算 | 4 +59 | 排序基本概念 | 3 +60 | 冒泡排序 | 3 +61 | 选择排序 | 3 +62 | 插入排序 | 3 +63 | 计数排序 | 3 +64 | 深度优先搜索(DFS) | 5 +65 | 广度优先搜索(BFS) | 5 +66 | 图的深度优先遍历 | 4 +67 | 图的广度优先遍历 | 4 +68 | 泛洪算法(Flood Fill) | 5 +69 | 动态规划基本思路 | 4 +70 | 简单一维动态规划 | 4 +71 | 简单背包类型动态规划 | 5 +72 | 简单区间类型动态规划 | 5 + +=== 2.1.5 数学与其他 === +73 | 自然数/整数/有理数/实数及运算 | 1 +74 | 进制与进制转换 | 1 +75 | 代数(初中部分) | 1 +76 | 几何(初中部分) | 1 +77 | 整除/因数/倍数/质数/合数 | 3 +78 | 取整 | 3 +79 | 模运算与取余 | 3 +80 | 整数唯一分解定理 | 3 +81 | 辗转相除法(欧几里得算法) | 3 +82 | 素数筛法(埃氏筛/线性筛) | 4 +83 | 集合 | 2 +84 | 加法原理 | 2 +85 | 乘法原理 | 2 +86 | 排列 | 4 +87 | 组合 | 4 +88 | 杨辉三角 | 4 +89 | ASCII码 | 2 + +请以JSON格式返回,格式如下: +[ + {"id": 1, "name": "知识点名称", "original_score": 1, "new_score": 2, "changed": true, "reason": "评分理由"}, + ... +] +""" + +response = client.chat.completions.create( + model="gpt-4.1-mini", + messages=[ + {"role": "system", "content": "你是NOI竞赛评分专家。请严格按照JSON格式返回评分结果。"}, + {"role": "user", "content": knowledge_points} + ], + temperature=0.3, + max_tokens=8000 +) + +result = response.choices[0].message.content +# Extract JSON from response +if "```json" in result: + result = result.split("```json")[1].split("```")[0] +elif "```" in result: + result = result.split("```")[1].split("```")[0] + +scores = json.loads(result) + +# Save to file +with open('/home/ubuntu/ai_scores.json', 'w', encoding='utf-8') as f: + json.dump(scores, f, ensure_ascii=False, indent=2) + +# Print summary +changed_count = sum(1 for s in scores if s.get('changed', False)) +print(f"总共评分 {len(scores)} 个知识点") +print(f"其中 {changed_count} 个知识点评分发生了变化") +print("\n评分变化的知识点:") +for s in scores: + if s.get('changed', False): + print(f" [{s['id']}] {s['name']}: {s['original_score']} -> {s['new_score']} ({s['reason']})") diff --git a/generate_detailed_doc.py b/generate_detailed_doc.py new file mode 100644 index 0000000..e400a5b --- /dev/null +++ b/generate_detailed_doc.py @@ -0,0 +1,1401 @@ +#!/usr/bin/env python3 +""" +生成NOI入门级完整详细学习文档(HTML格式,支持黄色高亮评分变化) +然后转换为PDF +""" +import json + +# 读取AI评分数据 +with open('/home/ubuntu/ai_scores.json', 'r', encoding='utf-8') as f: + scores = json.loads(f.read()) + +# 构建评分字典 +score_map = {} +for s in scores: + score_map[s['id']] = s + +def score_badge(sid, show_original=True): + """生成评分徽章HTML,如果评分变化则黄色高亮""" + s = score_map.get(sid, None) + if s is None: + return "" + if s['changed']: + return f'原始评分【{s["original_score"]}】→ AI重评【{s["new_score"]}】({s["reason"]})' + else: + return f'难度评级【{s["original_score"]}】' + +html = """ + + + +基于 NOI 大纲(2025年修订版) | 含全网调研AI重评分 | 详细知识点讲解与代码示例
+ +""" + score_badge(1) + """
+计算机系统由硬件和软件两大部分组成。硬件是计算机的物理组成部分,主要包括以下核心组件:
+| 组件 | 功能说明 | 竞赛关注点 |
|---|---|---|
| CPU(中央处理器) | 执行指令和运算的核心部件,包含运算器和控制器 | 理解时间复杂度的物理基础 |
| 内存(RAM) | 临时存储正在运行的程序和数据,断电后数据丢失 | 理解空间复杂度、数组大小限制 |
| 外存(硬盘/SSD) | 永久存储数据和程序 | 文件读写操作的基础 |
| 输入设备 | 键盘、鼠标等,用于向计算机输入数据 | 标准输入(stdin) |
| 输出设备 | 显示器、打印机等,用于输出处理结果 | 标准输出(stdout) |
""" + score_badge(2) + """
+操作系统(Operating System, OS)是管理计算机硬件和软件资源的系统软件。NOI竞赛环境主要使用Linux操作系统(NOI Linux 2.0,基于Ubuntu 20.04)。选手需要了解操作系统的基本功能:进程管理、内存管理、文件系统管理和设备管理。
+ +""" + score_badge(3) + """
+了解计算机网络的基本概念,包括局域网(LAN)、广域网(WAN)、Internet的基本架构、IP地址、域名系统(DNS)等。此部分在CSP-J初赛中偶有考察。
+ +""" + score_badge(4) + """
+了解计算机发展的重要里程碑:从ENIAC(1946年)到现代计算机。了解图灵(Alan Turing)、冯·诺依曼(John von Neumann)等计算机科学先驱的贡献。冯·诺依曼体系结构(存储程序概念)是现代计算机的基础架构。
+ +""" + score_badge(5) + """
+NOI(全国青少年信息学奥林匹克竞赛)由中国计算机学会(CCF)主办。竞赛体系包括:CSP-J/S(非专业级软件能力认证)→ NOIP(联赛)→ NOI(国赛)→ IOI(国际赛)。CSP-J为入门级认证,面向初中及以下学生。
+ +""" + score_badge(6) + """
+计算机中数据的最小单位是位(bit),只能存储0或1。8个位组成一个字节(Byte)。字(Word)的大小取决于CPU架构(32位或64位)。
+| 单位 | 大小 | 常见应用 |
|---|---|---|
| 1 bit | 0 或 1 | bool类型的逻辑值 |
| 1 Byte = 8 bits | 0~255(无符号) | char类型 |
| 4 Bytes = 32 bits | 约±21亿 | int类型 |
| 8 Bytes = 64 bits | 约±9.2×1018 | long long类型 |
long long类型的题目。当数据范围超过2×109时,必须使用long long。""" + score_badge(7) + """
+程序设计语言分为低级语言(机器语言、汇编语言)和高级语言(C、C++、Python等)。NOI系列竞赛使用C++语言。C++程序需要经过编译(将源代码转换为机器代码)才能运行,编译器将.cpp源文件编译为可执行文件。
""" + score_badge(8) + """
+掌握在Windows或Linux图形界面中进行文件和目录的基本操作:创建、复制、移动、删除、重命名文件和文件夹。
+ +""" + score_badge(9) + """
+常用的C++ IDE包括:Windows下的Dev-C++(轻量级,适合入门)、Code::Blocks(跨平台)、Visual Studio Code(功能强大)。Linux下可使用Code::Blocks或命令行编辑器(如vim、nano)配合g++编译器。
+ +""" + score_badge(10) + """
+g++是GNU C++编译器,是NOI竞赛环境中的标准编译器。基本使用方法:
++# 基本编译 +g++ -o program source.cpp + +# 带优化的编译(竞赛常用) +g++ -O2 -o program source.cpp + +# 编译并启用C++14标准 +g++ -std=c++14 -O2 -o program source.cpp + +# 运行程序 +./program ++ + + +
""" + score_badge(11) + """
+标识符是程序中用来命名变量、函数、类型等的名称,由字母、数字和下划线组成,不能以数字开头。关键字是C++语言保留的具有特殊含义的标识符(如int、if、for、return等),不能用作变量名。
+// 合法标识符 +int count = 0; +double totalScore = 95.5; +int _value = 10; + +// 非法标识符 +// int 2nd = 5; // 不能以数字开头 +// int class = 1; // class是关键字 ++ +
""" + score_badge(12) + """
+常量是程序运行期间值不会改变的量,使用const关键字定义。变量是可以在程序运行过程中改变其值的量。
+const int MAXN = 100005; // 常量,竞赛中常用于定义数组大小 +const double PI = 3.14159265358979; +int n, m; // 变量 ++ +
""" + score_badge(13) + """
+头文件包含了函数声明和宏定义。竞赛中常用#include <bits/stdc++.h>万能头文件(包含所有标准库)。名字空间用于避免命名冲突,竞赛中常用using namespace std;。
+#include <bits/stdc++.h> // 万能头文件(竞赛专用)
+using namespace std; // 使用标准命名空间
+
+int main() {
+ // 程序代码
+ return 0;
+}
+
+
+""" + score_badge(14) + """
+编辑是编写源代码的过程。编译是将源代码翻译成机器代码的过程(C++使用编译方式)。解释是逐行翻译并执行源代码(如Python)。调试是查找和修复程序错误的过程。
+ +""" + score_badge(15) + """
+| 类型 | 大小 | 范围 | 用途 |
|---|---|---|---|
int | 4字节 | -231 ~ 231-1(约±2.1×109) | 常规整数 |
long long | 8字节 | -263 ~ 263-1(约±9.2×1018) | 大整数 |
float | 4字节 | 约7位有效数字 | 单精度浮点(少用) |
double | 8字节 | 约15位有效数字 | 双精度浮点 |
char | 1字节 | -128 ~ 127 或 0 ~ 255 | 字符 |
bool | 1字节 | true(1) 或 false(0) | 逻辑值 |
long long,导致整数溢出。建议养成习惯:看到大数据范围立即使用long long。""" + score_badge(16) + """
+
+#include <bits/stdc++.h>
+using namespace std;
+int main() {
+ int n;
+ // C++风格输入输出
+ cin >> n;
+ cout << "n = " << n << endl;
+
+ // C风格输入输出(通常更快)
+ scanf("%d", &n);
+ printf("n = %d\\n", n);
+
+ return 0;
+}
+
+scanf/printf比cin/cout更快。如果使用cin/cout,可以添加ios::sync_with_stdio(false); cin.tie(0);来加速。""" + score_badge(17) + """
+
+// if-else语句
+if (score >= 90) {
+ cout << "优秀" << endl;
+} else if (score >= 60) {
+ cout << "及格" << endl;
+} else {
+ cout << "不及格" << endl;
+}
+
+// switch语句
+switch (grade) {
+ case 'A': cout << "优秀"; break;
+ case 'B': cout << "良好"; break;
+ default: cout << "其他"; break;
+}
+
+
+""" + score_badge(18) + """
+
+// for循环 - 最常用
+for (int i = 0; i < n; i++) {
+ // 循环体
+}
+
+// while循环
+while (条件) {
+ // 循环体
+}
+
+// do-while循环(至少执行一次)
+do {
+ // 循环体
+} while (条件);
+
+
+""" + score_badge(19) + """
+多层循环(嵌套循环)在竞赛中非常常见,用于处理二维数组、枚举多个变量等场景。需要注意时间复杂度:两层循环为O(n2),三层为O(n3)。
+
+// 打印九九乘法表
+for (int i = 1; i <= 9; i++) {
+ for (int j = 1; j <= i; j++) {
+ printf("%d×%d=%-3d", j, i, i * j);
+ }
+ printf("\\n");
+}
+
+
+""" + score_badge(20) + """
+| 运算类型 | 运算符 | 示例 | 说明 |
|---|---|---|---|
| 算术运算 | + - * | a + b | 加减乘 |
/ | 7 / 2 = 3 | 整数除法取整 | |
% | 7 % 2 = 1 | 取余(模运算) | |
++ -- | i++ | 自增自减 | |
?: | a>b ? a : b | 三目运算 | |
| 关系运算 | > >= < <= == != | a == b | 返回bool值 |
| 逻辑运算 | && || ! | a>0 && b>0 | 与、或、非 |
""" + score_badge(21) + """
+位运算直接操作二进制位,在竞赛中应用广泛(状态压缩、快速判断奇偶等)。
+| 运算符 | 名称 | 示例 | 结果 | 常见用途 |
|---|---|---|---|---|
& | 按位与 | 5 & 3 (101 & 011) | 1 (001) | 判断奇偶:n & 1 |
| | 按位或 | 5 | 3 (101 | 011) | 7 (111) | 设置某一位 |
^ | 按位异或 | 5 ^ 3 (101 ^ 011) | 6 (110) | 交换两数、加密 |
~ | 按位取反 | ~5 | -6 | 补码运算 |
<< | 左移 | 1 << 3 | 8 | 乘以2的幂 |
>> | 右移 | 8 >> 2 | 2 | 除以2的幂 |
+// 位运算常见技巧 +int n = 10; +if (n & 1) cout << "奇数"; else cout << "偶数"; // 判断奇偶 +int x = 1 << 10; // x = 1024,即2^10 +// 交换两个数(不用临时变量) +a ^= b; b ^= a; a ^= b; ++ +
""" + score_badge(22) + """
+| 函数 | 功能 | 示例 |
|---|---|---|
abs(x) | 绝对值 | abs(-5) = 5 |
sqrt(x) | 平方根 | sqrt(16) = 4.0 |
ceil(x) | 上取整 | ceil(3.2) = 4 |
floor(x) | 下取整 | floor(3.8) = 3 |
round(x) | 四舍五入 | round(3.5) = 4 |
pow(x,y) | x的y次方 | pow(2,10) = 1024 |
log(x) | 自然对数 | log(e) = 1.0 |
log2(x) | 以2为底的对数 | log2(8) = 3.0 |
""" + score_badge(23) + """ """ + score_badge(24) + """
+程序的三种基本结构:顺序结构(按顺序执行)、分支结构(条件判断)、循环结构(重复执行)。模块化程序设计将复杂问题分解为若干子问题,每个子问题用一个函数实现。
+ +""" + score_badge(25) + """
+数组是存储相同类型元素的连续内存空间。数组下标从0开始。
+
+int a[100005]; // 定义数组,竞赛中通常开大一些
+int n;
+cin >> n;
+for (int i = 0; i < n; i++) {
+ cin >> a[i]; // 读入数组
+}
+// 求数组元素之和
+long long sum = 0;
+for (int i = 0; i < n; i++) {
+ sum += a[i];
+}
+
+
+""" + score_badge(26) + """
++int grid[105][105]; // 二维数组,常用于矩阵、地图 +int n, m; +cin >> n >> m; +for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + cin >> grid[i][j]; ++ +
""" + score_badge(27) + """
+C++中处理字符串有两种方式:字符数组(C风格)和string类(C++风格,推荐)。
+
+// string类常用操作
+string s = "hello";
+int len = s.length(); // 长度:5
+s += " world"; // 拼接:"hello world"
+string sub = s.substr(0, 5); // 子串:"hello"
+int pos = s.find("world"); // 查找:6
+char c = s[0]; // 访问字符:'h'
+
+// 字符数组
+char str[105];
+scanf("%s", str);
+int len2 = strlen(str);
+
+
+""" + score_badge(28) + """
+
+// 函数定义
+int gcd(int a, int b) {
+ if (b == 0) return a;
+ return gcd(b, a % b); // 递归调用
+}
+
+// 函数调用
+int result = gcd(12, 8); // result = 4
+
+
+""" + score_badge(29) + """
+
+// 传值:函数内修改不影响原变量
+void addOne(int x) { x++; }
+
+// 传引用:函数内修改会影响原变量
+void addOne(int &x) { x++; }
+
+int a = 5;
+addOne(a); // 传引用后 a = 6
+
+
+""" + score_badge(30) + """
+
+// 结构体:将不同类型的数据组合在一起
+struct Student {
+ string name;
+ int score;
+ bool operator < (const Student &other) const {
+ return score > other.score; // 按分数降序排序
+ }
+};
+
+Student stu[105];
+sort(stu, stu + n); // 使用自定义排序
+
+
+""" + score_badge(31) + """
+指针存储变量的内存地址,引用是变量的别名。在竞赛中,指针主要用于链表、树等数据结构的实现。
++int x = 10; +int *p = &x; // p指向x的地址 +cout << *p; // 解引用,输出10 +*p = 20; // 通过指针修改x的值 + +int &ref = x; // ref是x的引用(别名) +ref = 30; // 等价于 x = 30 ++ +
""" + score_badge(32) + """
+
+// 文件重定向(竞赛常用)
+freopen("input.txt", "r", stdin);
+freopen("output.txt", "w", stdout);
+
+// C++文件流
+ifstream fin("input.txt");
+ofstream fout("output.txt");
+int n;
+fin >> n;
+fout << n << endl;
+
+
+""" + score_badge(33) + """
+
+#include <bits/stdc++.h>
+using namespace std;
+
+int a[] = {3, 1, 4, 1, 5, 9, 2, 6};
+int n = 8;
+
+sort(a, a + n); // 排序:1 1 2 3 4 5 6 9
+sort(a, a + n, greater<int>()); // 降序排序
+int mx = *max_element(a, a + n); // 最大值
+int mn = *min_element(a, a + n); // 最小值
+swap(a[0], a[1]); // 交换两个元素
+reverse(a, a + n); // 反转数组
+
+
+""" + score_badge(34) + """
+| 容器 | 特点 | 常用操作 | 竞赛应用 |
|---|---|---|---|
vector | 动态数组 | push_back, size, [] | 邻接表、动态存储 |
stack | 后进先出 | push, pop, top | 表达式求值、括号匹配 |
queue | 先进先出 | push, pop, front | BFS |
list | 双向链表 | push_back, insert | 频繁插入删除 |
+// vector示例
+vector<int> v;
+v.push_back(10);
+v.push_back(20);
+for (int i = 0; i < v.size(); i++) cout << v[i] << " ";
+
+// stack示例
+stack<int> st;
+st.push(1); st.push(2); st.push(3);
+while (!st.empty()) {
+ cout << st.top() << " "; // 输出 3 2 1
+ st.pop();
+}
+
+// queue示例(BFS常用)
+queue<int> q;
+q.push(1); q.push(2);
+while (!q.empty()) {
+ int front = q.front(); q.pop();
+ cout << front << " "; // 输出 1 2
+}
+
+
+
+
+""" + score_badge(35) + """
+链表是一种动态数据结构,每个节点包含数据域和指针域。与数组相比,链表支持O(1)的插入和删除,但不支持随机访问。
+
+// 静态链表(竞赛常用,避免动态内存分配)
+struct Node {
+ int val, next;
+} nodes[100005];
+int head = -1, cnt = 0;
+
+void insert(int val) { // 头插法
+ nodes[cnt] = {val, head};
+ head = cnt++;
+}
+
+
+""" + score_badge(36) + """
+栈是一种后进先出(LIFO)的数据结构。在CSP-J中,栈常用于表达式求值、括号匹配、单调栈等场景。
+
+// 括号匹配示例
+bool isValid(string s) {
+ stack<char> st;
+ for (char c : s) {
+ if (c == '(' || c == '[' || c == '{') st.push(c);
+ else {
+ if (st.empty()) return false;
+ char top = st.top(); st.pop();
+ if (c == ')' && top != '(') return false;
+ if (c == ']' && top != '[') return false;
+ if (c == '}' && top != '{') return false;
+ }
+ }
+ return st.empty();
+}
+
+
+""" + score_badge(37) + """
+队列是一种先进先出(FIFO)的数据结构。在CSP-J中,队列是BFS(广度优先搜索)的核心数据结构。
+ +""" + score_badge(38) + """
+树是一种非线性数据结构,由节点和边组成。重要概念包括:根节点、叶子节点(无子节点)、父节点、子节点、深度(根到该节点的路径长度)、高度(该节点到最深叶子的路径长度)。
+ +""" + score_badge(39) + """
+二叉树是每个节点最多有两个子节点(左子节点和右子节点)的树。基本性质:
+| 性质 | 描述 |
|---|---|
| 第i层最多节点数 | 2i-1 |
| 深度为k的二叉树最多节点数 | 2k - 1 |
| 叶子节点数 = 度为2的节点数 + 1 | n0 = n2 + 1 |
""" + score_badge(40) + """
+
+// 二叉树的数组存储(适用于完全二叉树)
+int tree[100005]; // tree[1]为根,tree[2i]为左子,tree[2i+1]为右子
+
+// 二叉树的链式存储
+struct TreeNode {
+ int val;
+ int left, right; // 左右子节点编号
+} nodes[100005];
+
+
+""" + score_badge(41) + """
+
+// 前序遍历:根 → 左 → 右
+void preorder(int u) {
+ if (u == -1) return;
+ cout << nodes[u].val << " ";
+ preorder(nodes[u].left);
+ preorder(nodes[u].right);
+}
+
+// 中序遍历:左 → 根 → 右
+void inorder(int u) {
+ if (u == -1) return;
+ inorder(nodes[u].left);
+ cout << nodes[u].val << " ";
+ inorder(nodes[u].right);
+}
+
+// 后序遍历:左 → 右 → 根
+void postorder(int u) {
+ if (u == -1) return;
+ postorder(nodes[u].left);
+ postorder(nodes[u].right);
+ cout << nodes[u].val << " ";
+}
+
+
+""" + score_badge(42) + """
+完全二叉树是除最后一层外每层都满的二叉树,最后一层的节点从左到右连续排列。可以用数组高效存储:节点i的左子节点为2i,右子节点为2i+1,父节点为i/2。
+ +""" + score_badge(43) + """
+哈夫曼树是带权路径长度最短的二叉树。构造方法:每次取权值最小的两个节点合并。哈夫曼编码是一种最优前缀编码,用于数据压缩。
+ +""" + score_badge(44) + """
+二叉搜索树满足:左子树所有节点值 < 根节点值 < 右子树所有节点值。中序遍历BST可以得到有序序列。
+ +""" + score_badge(45) + """
+图由顶点(Vertex)和边(Edge)组成。图分为有向图和无向图。重要概念:度(与顶点相连的边数)、路径、环、连通性。
+ +""" + score_badge(46) + """
+
+// 邻接矩阵(适用于稠密图)
+int adj[505][505]; // adj[i][j] = 1 表示i到j有边
+adj[u][v] = 1;
+adj[v][u] = 1; // 无向图
+
+// 邻接表(适用于稀疏图,竞赛常用)
+vector<int> G[100005];
+G[u].push_back(v);
+G[v].push_back(u); // 无向图
+
+// 带权邻接表
+vector<pair<int,int>> G[100005]; // {目标节点, 权值}
+G[u].push_back({v, w});
+
+
+
+
+""" + score_badge(47) + """ """ + score_badge(48) + """
+算法是解决特定问题的一系列明确步骤。算法的五个基本特性:有穷性、确定性、可行性、输入、输出。评价算法的主要指标是时间复杂度和空间复杂度。
+| 时间复杂度 | 名称 | n=106时操作次数 | 可行性 |
|---|---|---|---|
| O(1) | 常数 | 1 | 极快 |
| O(log n) | 对数 | 20 | 极快 |
| O(n) | 线性 | 106 | 快 |
| O(n log n) | 线性对数 | 2×107 | 可行 |
| O(n2) | 平方 | 1012 | 不可行 |
| O(2n) | 指数 | 极大 | 不可行 |
""" + score_badge(49) + """
+枚举法(暴力法)是最基础的算法思想:遍历所有可能的解,逐一检验是否满足条件。
+
+// 示例:找出1~n中所有质数
+for (int i = 2; i <= n; i++) {
+ bool isPrime = true;
+ for (int j = 2; j * j <= i; j++) {
+ if (i % j == 0) { isPrime = false; break; }
+ }
+ if (isPrime) cout << i << " ";
+}
+
+
+""" + score_badge(50) + """
+模拟法是按照题目描述的过程,用代码逐步模拟实现。这是CSP-J中出现频率最高的算法类型,几乎每年T1和T2都会考察。
+""" + score_badge(51) + """
+贪心算法在每一步都选择当前最优的方案,期望最终得到全局最优解。贪心算法不一定能得到最优解,但对于某些特定问题(如活动选择、哈夫曼编码)可以证明其正确性。
+
+// 经典贪心:活动选择问题
+// 给定n个活动的开始和结束时间,选择最多不冲突的活动
+struct Activity {
+ int start, end;
+};
+bool cmp(Activity a, Activity b) {
+ return a.end < b.end; // 按结束时间排序
+}
+sort(act, act + n, cmp);
+int count = 1, lastEnd = act[0].end;
+for (int i = 1; i < n; i++) {
+ if (act[i].start >= lastEnd) {
+ count++;
+ lastEnd = act[i].end;
+ }
+}
+
+
+""" + score_badge(52) + """
+递推法通过已知的初始值和递推关系,逐步计算后续结果。递推是动态规划的基础。
++// 斐波那契数列 +int fib[105]; +fib[1] = 1; fib[2] = 1; +for (int i = 3; i <= n; i++) + fib[i] = fib[i-1] + fib[i-2]; ++ +
""" + score_badge(53) + """
+递归是函数调用自身的编程技巧。递归需要满足两个条件:基准情形(终止条件)和递归步骤(问题规模缩小)。
+
+// 汉诺塔问题
+void hanoi(int n, char from, char to, char aux) {
+ if (n == 1) {
+ cout << from << " -> " << to << endl;
+ return;
+ }
+ hanoi(n - 1, from, aux, to);
+ cout << from << " -> " << to << endl;
+ hanoi(n - 1, aux, to, from);
+}
+
+
+""" + score_badge(54) + """
+二分法将搜索范围每次缩小一半,时间复杂度O(log n)。应用场景:有序数组查找、二分答案。
+
+// 二分查找
+int binarySearch(int a[], int n, int target) {
+ int left = 0, right = n - 1;
+ while (left <= right) {
+ int mid = left + (right - left) / 2;
+ if (a[mid] == target) return mid;
+ else if (a[mid] < target) left = mid + 1;
+ else right = mid - 1;
+ }
+ return -1; // 未找到
+}
+
+// 二分答案(竞赛高频模板)
+int left = 0, right = 1e9;
+while (left < right) {
+ int mid = (left + right) / 2;
+ if (check(mid)) right = mid; // check函数判断mid是否可行
+ else left = mid + 1;
+}
+// left就是答案
+
+""" + score_badge(55) + """
+倍增法是一种以2的幂次为步长进行跳跃的算法思想。常用于求解LCA(最近公共祖先)、稀疏表(ST表)等问题。核心思想:将任意整数分解为若干2的幂次之和。
+ +""" + score_badge(56) + """
+前缀和是一种预处理技巧,可以在O(1)时间内求出数组任意区间的和。
++// 一维前缀和 +int a[100005], prefix[100005]; +prefix[0] = 0; +for (int i = 1; i <= n; i++) + prefix[i] = prefix[i-1] + a[i]; + +// 查询区间[l, r]的和 +int sum = prefix[r] - prefix[l-1]; + +// 二维前缀和 +int s[505][505]; +for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j]; ++ +
""" + score_badge(57) + """
+差分是前缀和的逆运算。差分数组可以在O(1)时间内对数组的一个区间进行加减操作。
+
+// 差分数组
+int diff[100005] = {0};
+
+// 对区间[l, r]的所有元素加val
+diff[l] += val;
+diff[r + 1] -= val;
+
+// 还原原数组
+for (int i = 1; i <= n; i++)
+ diff[i] += diff[i-1]; // diff[i]就是原数组a[i]的值
+
+
+""" + score_badge(58) + """
+当数值超过long long的范围时,需要使用高精度运算(用数组模拟大数运算)。
+// 高精度加法
+string add(string a, string b) {
+ string result = "";
+ int carry = 0;
+ int i = a.size() - 1, j = b.size() - 1;
+ while (i >= 0 || j >= 0 || carry) {
+ int sum = carry;
+ if (i >= 0) sum += a[i--] - '0';
+ if (j >= 0) sum += b[j--] - '0';
+ result = char(sum % 10 + '0') + result;
+ carry = sum / 10;
+ }
+ return result;
+}
+
+
+""" + score_badge(59) + """
+ +| 算法 | 时间复杂度(平均) | 时间复杂度(最坏) | 空间复杂度 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 | O(n2) | O(n2) | O(1) | 稳定 |
| 选择排序 | O(n2) | O(n2) | O(1) | 不稳定 |
| 插入排序 | O(n2) | O(n2) | O(1) | 稳定 |
| 计数排序 | O(n+k) | O(n+k) | O(k) | 稳定 |
| sort(STL) | O(n log n) | O(n log n) | O(log n) | 不稳定 |
+// 冒泡排序
+for (int i = 0; i < n - 1; i++)
+ for (int j = 0; j < n - 1 - i; j++)
+ if (a[j] > a[j+1]) swap(a[j], a[j+1]);
+
+// 选择排序
+for (int i = 0; i < n - 1; i++) {
+ int minIdx = i;
+ for (int j = i + 1; j < n; j++)
+ if (a[j] < a[minIdx]) minIdx = j;
+ swap(a[i], a[minIdx]);
+}
+
+// 插入排序
+for (int i = 1; i < n; i++) {
+ int key = a[i], j = i - 1;
+ while (j >= 0 && a[j] > key) {
+ a[j+1] = a[j]; j--;
+ }
+ a[j+1] = key;
+}
+
+// 计数排序(适用于值域较小的情况)
+int cnt[100005] = {0};
+for (int i = 0; i < n; i++) cnt[a[i]]++;
+int idx = 0;
+for (int i = 0; i <= maxVal; i++)
+ while (cnt[i]--) a[idx++] = i;
+
+
+""" + score_badge(64) + """
+DFS沿着一条路径尽可能深入,直到无法继续时回溯。通常用递归或栈实现。
+
+// DFS模板 - 全排列
+int n, path[15];
+bool used[15];
+
+void dfs(int depth) {
+ if (depth == n) {
+ for (int i = 0; i < n; i++) cout << path[i] << " ";
+ cout << endl;
+ return;
+ }
+ for (int i = 1; i <= n; i++) {
+ if (!used[i]) {
+ used[i] = true;
+ path[depth] = i;
+ dfs(depth + 1);
+ used[i] = false; // 回溯
+ }
+ }
+}
+
+
+""" + score_badge(65) + """
+BFS逐层扩展搜索,使用队列实现。BFS可以找到最短路径(边权相同时)。
+
+// BFS模板 - 迷宫最短路
+int dx[] = {0, 0, 1, -1};
+int dy[] = {1, -1, 0, 0};
+int dist[505][505];
+bool vis[505][505];
+
+void bfs(int sx, int sy) {
+ queue<pair<int,int>> q;
+ q.push({sx, sy});
+ vis[sx][sy] = true;
+ dist[sx][sy] = 0;
+ 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] && grid[nx][ny] != '#') {
+ vis[nx][ny] = true;
+ dist[nx][ny] = dist[x][y] + 1;
+ q.push({nx, ny});
+ }
+ }
+ }
+}
+
+
+""" + score_badge(66) + """ """ + score_badge(67) + """
+
+// 图的DFS遍历
+bool vis[100005];
+void dfs(int u) {
+ vis[u] = true;
+ for (int v : G[u]) {
+ if (!vis[v]) dfs(v);
+ }
+}
+
+// 图的BFS遍历
+void bfs(int start) {
+ queue<int> q;
+ q.push(start);
+ vis[start] = true;
+ while (!q.empty()) {
+ int u = q.front(); q.pop();
+ for (int v : G[u]) {
+ if (!vis[v]) {
+ vis[v] = true;
+ q.push(v);
+ }
+ }
+ }
+}
+
+
+""" + score_badge(68) + """
+泛洪算法用于填充连通区域,常用于统计连通块数量、图像填色等问题。
+
+// Flood Fill - 统计连通块数量
+int n, m, grid[505][505];
+bool vis[505][505];
+int dx[] = {0, 0, 1, -1};
+int dy[] = {1, -1, 0, 0};
+
+void floodFill(int x, int y, int color) {
+ vis[x][y] = true;
+ 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] && grid[nx][ny] == color) {
+ floodFill(nx, ny, color);
+ }
+ }
+}
+
+// 统计连通块数量
+int count = 0;
+for (int i = 0; i < n; i++)
+ for (int j = 0; j < m; j++)
+ if (!vis[i][j]) {
+ floodFill(i, j, grid[i][j]);
+ count++;
+ }
+
+
+""" + score_badge(69) + """
+动态规划(DP)是解决最优化问题的核心算法思想。DP的核心要素:
+| 要素 | 说明 |
|---|---|
| 最优子结构 | 问题的最优解包含子问题的最优解 |
| 重叠子问题 | 不同的决策路径会产生相同的子问题 |
| 状态定义 | 用数组dp[i]表示到第i个阶段的最优解 |
| 状态转移方程 | 描述状态之间的递推关系 |
| 边界条件 | 初始状态的值 |
""" + score_badge(70) + """
+
+// 经典问题:最长递增子序列(LIS)
+// dp[i] = 以a[i]结尾的最长递增子序列长度
+int dp[100005];
+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);
+ }
+}
+int ans = *max_element(dp, dp + n);
+
+// 经典问题:爬楼梯
+// dp[i] = 到达第i级台阶的方案数
+dp[1] = 1; dp[2] = 2;
+for (int i = 3; i <= n; i++)
+ dp[i] = dp[i-1] + dp[i-2];
+
+
+""" + score_badge(71) + """
+
+// 0-1背包问题
+// n个物品,背包容量W,第i个物品重量w[i],价值v[i]
+// dp[j] = 容量为j时的最大价值
+int dp[100005] = {0};
+for (int i = 1; i <= n; i++)
+ for (int j = W; j >= w[i]; j--) // 逆序遍历!
+ dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
+cout << dp[W];
+
+// 完全背包问题(每种物品可以选无限次)
+for (int i = 1; i <= n; i++)
+ for (int j = w[i]; j <= W; j++) // 正序遍历!
+ dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
+
+
+""" + score_badge(72) + """
+
+// 区间DP模板:石子合并
+// dp[i][j] = 合并第i堆到第j堆石子的最小代价
+int dp[505][505], prefix[505];
+memset(dp, 0x3f, sizeof(dp));
+for (int i = 1; i <= n; i++) dp[i][i] = 0;
+
+for (int len = 2; len <= n; len++) { // 枚举区间长度
+ for (int i = 1; i + len - 1 <= n; i++) { // 枚举左端点
+ int j = i + len - 1; // 右端点
+ for (int k = i; k < j; k++) { // 枚举分割点
+ dp[i][j] = min(dp[i][j],
+ dp[i][k] + dp[k+1][j] + prefix[j] - prefix[i-1]);
+ }
+ }
+}
+
+
+
+
+""" + score_badge(73) + """
+了解自然数、整数、有理数、实数的概念及其四则运算。在计算机中,整数和浮点数的表示方式不同,需要注意精度问题。
+ +""" + score_badge(74) + """
+
+// 十进制转其他进制
+void toBase(int n, int base) {
+ if (n == 0) return;
+ toBase(n / base, base);
+ cout << n % base;
+}
+
+// 其他进制转十进制
+int toDecimal(string s, int base) {
+ int result = 0;
+ for (char c : s) {
+ result = result * base + (c - '0');
+ }
+ return result;
+}
+
+
+""" + score_badge(75) + """ """ + score_badge(76) + """
+掌握初中阶段的代数知识(一元一次方程、一元二次方程、不等式等)和几何知识(三角形、四边形、圆的面积和周长等)。CSP-J 2023年T3就考察了一元二次方程的求解。
+ +""" + score_badge(77) + """
+
+// 判断质数
+bool isPrime(int n) {
+ if (n < 2) return false;
+ for (int i = 2; i * i <= n; i++)
+ if (n % i == 0) return false;
+ return true;
+}
+
+// 分解质因数
+void factorize(int n) {
+ for (int i = 2; i * i <= n; i++) {
+ while (n % i == 0) {
+ cout << i << " ";
+ n /= i;
+ }
+ }
+ if (n > 1) cout << n;
+}
+
+
+""" + score_badge(78) + """
+上取整:ceil(a/b) = (a + b - 1) / b(整数除法技巧)。下取整:C++中整数除法默认下取整。
""" + score_badge(79) + """
+模运算的基本性质:(a + b) % m = ((a % m) + (b % m)) % m,乘法同理。竞赛中常见"答案对109+7取模"。
+const int MOD = 1e9 + 7;
+long long ans = 0;
+for (int i = 0; i < n; i++) {
+ ans = (ans + a[i]) % MOD;
+}
+
+
+""" + score_badge(80) + """
+任何大于1的正整数都可以唯一地分解为若干质数的乘积:n = p1a1 × p2a2 × ... × pkak。
+ +""" + score_badge(81) + """
+
+// 最大公约数(GCD)
+int gcd(int a, int b) {
+ return b == 0 ? a : gcd(b, a % b);
+}
+
+// 最小公倍数(LCM)
+int lcm(int a, int b) {
+ return a / gcd(a, b) * b; // 先除后乘防溢出
+}
+
+// C++14起可直接使用 __gcd(a, b)
+
+
+""" + score_badge(82) + """
+
+// 埃氏筛法 O(n log log n)
+bool notPrime[10000005];
+void sieve(int n) {
+ notPrime[0] = notPrime[1] = true;
+ for (int i = 2; i * i <= n; i++) {
+ if (!notPrime[i]) {
+ for (int j = i * i; j <= n; j += i)
+ notPrime[j] = true;
+ }
+ }
+}
+
+// 线性筛(欧拉筛)O(n)
+int primes[1000005], cnt = 0;
+bool notPrime2[10000005];
+void linearSieve(int n) {
+ for (int i = 2; i <= n; i++) {
+ if (!notPrime2[i]) primes[cnt++] = i;
+ for (int j = 0; j < cnt && i * primes[j] <= n; j++) {
+ notPrime2[i * primes[j]] = true;
+ if (i % primes[j] == 0) break;
+ }
+ }
+}
+
+
+""" + score_badge(83) + """ """ + score_badge(84) + """ """ + score_badge(85) + """
+加法原理:完成一件事有n类方法,第i类有ai种,总方法数为 Σai。乘法原理:完成一件事需要n个步骤,第i步有ai种方法,总方法数为 Πai。
+ +""" + score_badge(86) + """ """ + score_badge(87) + """
+排列:从n个元素中取r个排列,P(n,r) = n!/(n-r)!。组合:从n个元素中取r个组合,C(n,r) = n!/(r!(n-r)!)。
+
+// 计算组合数 C(n, r)
+long long C[1005][1005];
+void initC(int maxn) {
+ for (int i = 0; i <= maxn; i++) {
+ C[i][0] = 1;
+ for (int j = 1; j <= i; j++)
+ C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
+ }
+}
+
+
+""" + score_badge(88) + """
+杨辉三角的第n行第k个数就是组合数C(n,k)。杨辉三角的递推关系:C(n,k) = C(n-1,k-1) + C(n-1,k)。
+ +""" + score_badge(89) + """
+| 字符 | ASCII码 | 常用关系 |
|---|---|---|
| '0'~'9' | 48~57 | 数字字符转数字:c - '0' |
| 'A'~'Z' | 65~90 | 大写转小写:c + 32 或 c + 'a' - 'A' |
| 'a'~'z' | 97~122 | 小写转大写:c - 32 或 c - 'a' + 'A' |
以下表格列出了所有经过AI模型重新评估后评分发生变化的知识点(黄色高亮标记)。评分基于全网深度调研数据,综合考虑考试重要性、学习难度、区分度和实用性四个维度。
+ +| 编号 | 知识点 | 原始评分 | AI重评分 | 变化 | 评分理由 |
|---|---|---|---|---|---|
| {s["id"]} | {s["name"]} | 【{s["original_score"]}】 | 【{s["new_score"]}】 | {arrow} | {s["reason"]} |
| {s["id"]} | {s["name"]} | 【{s["original_score"]}】 | 【{s["new_score"]}】 | - | {s["reason"]} |
+— 文档生成日期:2026年3月14日 | 基于 NOI 大纲(2025年修订版)— +
+ + + +""" + +with open('/home/ubuntu/NOI_Beginner_Guide_2025.html', 'w', encoding='utf-8') as f: + f.write(html) + +print(f"HTML document generated successfully. Total length: {len(html)} chars") +print(f"Total knowledge points: {len(scores)}") +print(f"Changed scores: {sum(1 for s in scores if s['changed'])}") diff --git a/noi_syllabus_beginner_part1.txt b/noi_syllabus_beginner_part1.txt new file mode 100644 index 0000000..091e83d --- /dev/null +++ b/noi_syllabus_beginner_part1.txt @@ -0,0 +1,93 @@ +NOI大纲(2025年修订版)完整内容提取 + +=== 2.1 入门级 === + +2.1.1 基础知识与编程环境 +1. 【1】计算机的基本构成(CPU、内存、I/O设备等) +2. 【1】Windows、Linux等操作系统的基本概念及其常见操作 +3. 【1】计算机网络和Internet的基本概念 +4. 【1】计算机的历史和常见用途 +5. 【1】NOI以及相关活动的历史 +6. 【1】NOI以及相关活动的规则 +7. 【1】位、字节与字 +8. 【1】程序设计语言以及程序编译和运行的基本概念 +9. 【1】使用图形界面新建、复制、删除、移动文件或目录 +10. 【1】使用Windows系统下的集成开发环境(例如Dev-C++等) +11. 【1】使用Linux系统下的集成开发环境(例如Code::Blocks等) +12. 【1】常用编译命令g++的基本使用 + +2.1.2 C++程序设计 +1. 程序基本概念 + - 【1】标识符、关键字、常量、变量、字符串、表达式的概念 + - 【1】常量与变量的命名、定义及作用 + - 【2】头文件与名字空间的概念 + - 【2】编辑、编译、解释、调试的概念 + +2. 基本数据类型 + - 【1】整数型:int、long long + - 【1】实数型:float、double + - 【1】字符型:char + - 【1】布尔型:bool + +3. 程序基本语句 + - 【2】cin语句、scanf语句、cout语句、printf语句、赋值语句、复合语句 + - 【2】if语句、switch语句、多层条件语句 + - 【2】for语句、while语句、do while语句 + - 【3】多层循环语句 + +4. 基本运算 + - 【1】算术运算:加、减、乘、除、整除、求余 + - 【1】关系运算:大于、大于等于、小于、小于等于、等于、不等于 + - 【1】逻辑运算:与(&&)、或(||)、非(!) + - 【1】变量自增与自减运算 + - 【1】三目运算 + - 【2】位运算:与(&)、或(|)、非(~)、异或(^)、左移(<<)、右移(>>) + +5. 数学库常用函数 + - 【3】绝对值函数、四舍五入函数、下取整函数、上取整函数、平方根函数、常用三角函数、对数函数、指数函数 + +6. 结构化程序设计 + - 【1】顺序结构、分支结构和循环结构 + - 【2】自顶向下、逐步求精的模块化程序设计 + - 【2】流程图的概念及流程图描述 + +7. 数组 + - 【1】数组与数组下标 + - 【1】数组的读入与输出 + - 【3】二维数组与多维数组 + +8. 字符串的处理 + - 【2】字符数组与相关函数 + - 【2】string类与相关函数 + +9. 函数与递归 + - 【2】函数定义与调用、形参与实参 + - 【3】传值参数与传引用参数 + - 【2】常量与变量的作用范围 + - 【2】递归函数 + +10. 结构体与联合体 + - 【3】结构体 + - 【3】联合体 + +11. 指针与引用 + - 【4】指针 + - 【4】基于指针的数组访问 + - 【4】字符指针 + - 【4】指向结构体的指针 + - 【5】引用 + +12. 文件及基本读写 + - 【2】文件的基本概念、文本文件的基本操作 + - 【2】文本文件类型与二进制文件类型 + - 【2】文件重定向、文件读写等操作 + +13. STL模板 + - 【3】常用函数与算法模板:min、max、swap、sort + - 【4】栈(stack)、队列(queue)、链表(list)、向量(vector)等容器 + +2.1.3 数据结构 +1. 线性结构 + - 【3】链表:单链表、双向链表、循环链表 + - 【3】栈 + - 【3】队列 diff --git a/noi_syllabus_beginner_part2.txt b/noi_syllabus_beginner_part2.txt new file mode 100644 index 0000000..95b878f --- /dev/null +++ b/noi_syllabus_beginner_part2.txt @@ -0,0 +1,114 @@ +继续提取 - 入门级后半部分 + +2.1.3 数据结构(续) +2. 简单树 + - 【3】树的定义与相关概念 + - 【4】树的表示与存储 + - 【3】二叉树的定义与基本性质 + - 【4】二叉树的表示与存储 + - 【4】二叉树的遍历:前序、中序、后序 + +3. 特殊树 + - 【4】完全二叉树的定义与基本性质 + - 【4】完全二叉树的数组表示法 + - 【4】哈夫曼树的定义和构造、哈夫曼编码 + - 【4】二叉搜索树的定义和构造 + +4. 简单图 + - 【3】图的定义与相关概念 + - 【4】图的表示与存储:邻接矩阵 + - 【4】图的表示与存储:邻接表 + +2.1.4 算法 +1. 算法概念与描述 + - 【1】算法概念 + - 【2】算法描述:自然语言描述、流程图描述、伪代码描述 + +2. 入门算法 + - 【1】枚举法 + - 【1】模拟法 + +3. 基础算法 + - 【3】贪心法 + - 【3】递推法 + - 【4】递归法 + - 【4】二分法 + - 【4】倍增法 + +4. 算法策略 + - 【3】前缀和 + - 【4】差分 + +5. 数值处理算法 + - 【4】高精度的加法 + - 【4】高精度的减法 + - 【4】高精度的乘法 + - 【4】高精度整数除以单精度整数的商和余数 + +6. 排序算法 + - 【3】排序的基本概念 + - 【3】冒泡排序 + - 【3】选择排序 + - 【3】插入排序 + - 【3】计数排序 + +7. 搜索算法 + - 【5】深度优先搜索 + - 【5】广度优先搜索 + +8. 图论算法 + - 【4】深度优先遍历 + - 【4】广度优先遍历 + - 【5】泛洪算法(Flood Fill) + +9. 动态规划 + - 【4】动态规划的基本思路 + - 【4】简单一维动态规划 + - 【5】简单背包类型动态规划 + - 【5】简单区间类型动态规划 + +2.1.5 数学与其他 +1. 数及其运算 + - 【1】自然数、整数、有理数、实数及其算术运算(加、减、乘、除) + - 【1】进制与进制转换:二进制、八进制、十进制、十六进制 + +2. 初等数学 + - 【1】代数(初中部分) + - 【1】几何(初中部分) + +3. 初等数论 + - 【3】整除、因数、倍数、指数、质(素)数、合数 + - 【3】取整 + - 【3】模运算与取余 + - 【3】整数唯一分解定理 + - 【3】辗转相除法(欧几里得算法) + - 【4】素数筛法:埃氏筛法与线性筛法 + +4. 离散与组合数学 + - 【2】集合 + - 【2】加法原理 + - 【2】乘法原理 + - 【4】排列 + - 【4】组合 + - 【4】杨辉三角 + +5. 其他 + - 【2】ASCII码 + +=== 2.2 提高级 === + +2.2.1 基础知识与编程环境 +1. 【5】Linux系统终端中常用的文件与目录操作命令 +2. 【5】Linux系统下常见文本编辑工具的使用 +3. 【5】常用编译命令g++与相关编译选项 +4. 【5】在Linux系统终端中运行程序,使用time命令查看程序用时 +5. 【5】调试工具GDB的使用 + +2.2.2 C++程序设计 +1. 类(class) + - 【6】类的概念及简单应用 + - 【6】成员函数和运算符重载 + +2. STL模板 + - 【5】容器(container)和迭代器(iterator) + - 【5】对(pair)、元组(tuple) diff --git a/research_findings.txt b/research_findings.txt new file mode 100644 index 0000000..6d5740d --- /dev/null +++ b/research_findings.txt @@ -0,0 +1,30 @@ +CSP-J历年真题考点分析(2010-2023)关键发现 +来源: https://blog.csdn.net/abilix_tony/article/details/145165078 + +T1(最简单):模拟、整数拆分、数位分离、字符串基础 → 近年需要时间复杂度优化和数学思维 +T2:以模拟为主,2019年起每题都需要时间复杂度优化。涉及贪心、排序、队列、二分 +T3:DP出现频率最高(线性DP/背包DP),其次是数据结构(栈/队列/树)、字符串大模拟、搜索(DFS/BFS) +T4:DP/图论/树型数据结构出现频率最高。图论只在T4出现(BFS/DFS/最短路/拓扑排序) + +高频考点排名(按出现频率): +1. 模拟法 - 几乎每年必考(T1/T2高频) +2. 动态规划(线性DP/背包DP) - T3/T4高频 +3. 数学/数论 - 近年趋势上升 +4. 排序算法 - 常考 +5. 贪心法 - T2/T4常考 +6. 搜索(DFS/BFS) - T3/T4常考 +7. 字符串处理 - T1/T2常考 +8. 数据结构(栈/队列/树) - T3/T4常考 +9. 枚举法 - T1/T2常考 +10. 图论(最短路/拓扑排序) - T4偶尔考 + +重要趋势: +- 近年难度持续上升 +- 时间复杂度优化成为标配 +- 数学思维考察增多 +- DP是拉开差距的关键 + +NOI大纲难度系数说明: +- 入门级知识点难度系数范围:1~5 +- 提高级知识点难度系数范围:5~8 +- NOI级知识点难度系数范围:7~10