Initial commit: C++ courseware

This commit is contained in:
xiaolinquan committed 2026-11-05 22:51:02 +08:00
commit 4a4ee7c287
1789 files changed
+373489

No files matched your search

@@ -0,0 +1,980 @@
# CSP-J 第二轮 核心知识讲义
## 一、要考试的范围有哪些
C++ 基础知识,基本的算法:枚举、模拟、排序、贪心、前缀和、差分、二分、搜索和动态规划、高精度运算,数据结构:栈、队列、树与常用数学知识。
## 二、C++ 基础知识
### 1. 数据类型与溢出
常见竞赛环境中的 32 位 `int` 最大值约为 21 亿,64 位 `long long` 最大值约为 $9.22\times10^{18}$。输入能装下,不代表计算结果也能装下。例如两个数都不超过十亿,各自能放进 `int`,相乘却可能达到 $10^{18}$。
```cpp
int a = 1000000000, b = 1000000000;
long long product = 1LL * a * b; // 或者(long long)a * b
```
这里的 `1LL` 是 `long long` 类型的整数 1,让右侧乘法从一开始就按 `long long` 计算。如果只写 `long long product = a * b;`,右侧可能先按 `int` 运算而溢出,再把错误结果赋给左侧变量。左侧类型再大,也无法补回已经丢失的结果。
累加时也要这样估计。十万个数,每个最多十亿,总和可达 $10^{14}$,因此答案和保存中间结果的前缀和数组,都需要足够大的类型。
整数类型要防溢出,`double` 则要留意近似误差。计数、循环次数,以及能换成整数单位的金额,尽量用整数处理。比较两个近似值时,可以用 `if(abs(a - b) < eps)` 判断它们是否足够接近。`eps` 是允许误差,例如 `1e-5`,具体取多大要看题目要求和数值范围。
### 2. 整数除法
两个整数相除,结果会向 0 截断,例如 `5 / 2` 得到 2。需要小数时,让其中一个数先变成浮点数:
```cpp
double x = 1 / 2; // 结果为 0
double y = 1.0 / 2; // 结果为 0.5
```
对非负整数 a 和正整数 b,向上取整常用下面两种方式:
```cpp
long long x = (a + b - 1) / b; // 整数方式,保证加法不溢出
long long y = ceil(1.0 * a / b); // 浮点方式,适用于数值和精度允许时
```
`ceil` 会把结果向上取整,a、b 都是整数时,要先乘 `1.0` 让除法产生小数;直接写 `ceil(a / b)`,里面已经完成了整数除法。如果 a 或 b 本来就是浮点数,才可以直接写 `ceil(a / b)`。
### 3. 条件与运算符
比较两个值时,用 `==` 判断相等,`!=` 判断不相等,大小比较使用 `<`、`<=`、`>`、`>=`。其中最容易写错的是等号:`=` 用来赋值,判断相等要写两个等号。
多个条件可以用 `&&` 表示“都成立”,用 `||` 表示“至少一个成立”,用 `!` 表示“取反”。例如判断 x 是否在闭区间内,要写 `l <= x && x <= r`,不能写成连续比较 `l <= x <= r`。
访问数组时,把边界判断放在前面:
```cpp
if (pos >= 0 && pos < n && a[pos] == target) {
// pos 合法,并且找到了目标
}
```
这样写,`&&` 前面的条件一旦不成立,后面就不再计算。下标越界时,程序不会继续访问这个数组位置。
### 4. 数组与 vector
数组通过下标访问元素。声明 `int a[100] = {};`,就建立了 100 个初值为 0 的位置,合法下标为 0~99。采用 1~n 编号时,至少开 n+1 个位置。
需要随时添加或删除末尾元素时,可以使用长度能够调整的数组 `vector`。常见的建立方式如下:
```cpp
vector<int> a; // 空容器,还没有元素
vector<int> b(5); // 5 个元素,初值都是 0
vector<int> c(5, -1); // 5 个元素,初值都是 -1
```
这几种写法建立出的长度不同:`b` 有 5 个元素,可以访问下标 0~4;`a` 还是空的,要先添加元素,才能访问 `a[0]`。添加、删除和查询长度时,常用下面这些操作:
| 操作 | 写法 | 含义 |
| --- | --- | --- |
| 在末尾添加 | `v.push_back(x)` | 新增一个值为 x 的元素,长度增加 1 |
| 按下标访问 | `v[i]` | 读取或修改已有的第 i 项,下标从 0 开始 |
| 访问最后一个元素 | `v.back()` | 读取或修改最后一个元素,容器必须非空 |
| 删除最后一个元素 | `v.pop_back()` | 长度减少 1,不返回被删除的元素,容器必须非空 |
| 查询长度 | `v.size()` | 得到当前元素个数 |
| 判断是否为空 | `v.empty()` | 没有元素时返回真 |
| 删除全部元素 | `v.clear()` | 长度变成 0,原来的下标都不能再使用 |
例如从空容器开始,依次 `push_back(2)`、`push_back(4)`,内容就变成 `{2,4}`;再执行 `pop_back()`,就只剩 `{2}`。
读入 n 个数,可以先建立 n 个元素,再按下标读入:
```cpp
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
```
读入后,就可以按下标逐个访问。循环中用 `size()` 取得当前长度:
```cpp
for (int i = 0; i < a.size(); i++) {
cout << a[i] << ' ';
}
```
只需要依次查看元素时,也可以写 `for (int x : a)`;要排序整个容器,就用 `sort(a.begin(), a.end())`。注意读入时要分清“放进已有位置”和“在末尾追加”:如果初始化为 `vector<int> a(n)` 代表着已经有 n 个元素,再用 `push_back` 添加 n 个数,长度就会变成 2n。
### 5. 字符和字符串
字符串同样可以按下标逐个处理,不过取出来的是字符。数字字符 `'7'` 与整数 `7` 不同,已知字符 `c` 是数字时,用 `c - '0'` 才能得到对应的数值。
```cpp
string s;
cin >> s;
int n = s.size();
for (int i = 0; i < n; i++) {
// 处理 s[i]
}
```
字符串有效字符的下标为 0~n−1。`cin >> s` 读取一个不含空白的字符串;要读取含空格的一整行,就用 `getline(cin, s)`。
#### 例:读入一个整数和下一行文字
第一行给出整数 n,第二行是可能含空格的文字。在这种数字后面紧接换行的情况,就需要在 `cin >> n` 后加一次 `cin.ignore()`,再读下一行:
```cpp
int n;
string s;
cin >> n;
cin.ignore();
getline(cin, s);
```
之所以多这一步,是因为 `cin >> n` 读走数字后,会留下行末换行。`getline` 直接遇到它就结束读取,于是得到空串;`cin.ignore()` 默认丢弃一个字符,在这里正好取走换行。数字后若还有多个空格,可改用 `cin.ignore(INT_MAX, '\n');` 丢弃本行剩余内容。连续用 `getline` 读多行时,上一次已经取走了换行,不用再额外调用 `ignore()`。
除了读入方式,还要分清楚字符串的比较规则:字符串的比较是按字典序比较,在比较时,`"10"` 会排在 `"2"` 前面,和整数的大小顺序不同。
### 6. 循环与函数
`break` 退出最近的一层循环;`continue` 跳过本轮剩下的操作。对于 `for`,执行 `continue` 后仍会执行第三部分的更新;对于 `while`,则直接回到条件判断,写在后面的更新语句可能被跳过。
`return` 结束当前函数。在 `main` 中执行 `return 0;` 会结束整个程序,在搜索函数里执行它则只是返回上一层调用。
如果函数里改过一个值,回到调用处却没变,可以先查传参方式。普通的值参数保存的是副本,通过引用参数才能直接修改对应的原变量。递归时也一样,每一层的局部变量各自独立,全局数组则由各层共用,修改后是否恢复要看它的用途。
自增自减运算放进一个表达式时,`i++` 代表的先用后加,`++i` 代表的先加后用。
### 7. 输入输出
使用 `cin`、`cout` 时,可以在正式读写前设置:
```cpp
ios::sync_with_stdio(false);
cin.tie(nullptr);
```
关闭同步后,读取数据的速率会大大加快,但是就要统一使用 `cin/cout` 来输入输出,避免与 `scanf`、`printf` 交错使用。一般换行用 `'\n'`,不必每次都用会刷新缓冲区的 `endl`。
对于复赛的题目,明确要求了要使用文件输入输出,就要按题面给出的文件名设置,例如:
```cpp
freopen("task.in", "r", stdin);
freopen("task.out", "w", stdout);
```
这里的 `task` 是示意名称,必须替换成题面要求的名称,并放在正式读写之前。
## 三、通过数据范围推测算法
语法能写对之后,还要判断算法能否在规定时间内跑完。看到 n 的上限,可以先按下面的范围筛选。这里按 C++、约 1~2 秒、循环体只做简单操作来粗估;接近上限时,仍要计算实际工作量。大量输出、长字符串比较和多组数据,都会增加耗时。
| 方法 | 大致工作量 | 通常可考虑的 n 范围 |
| --- | --- | --- |
| 枚举所有子集 | $2^n$ | 通常先考虑 $n\le20$;每个子集还要遍历 n 项时,应按 $n2^n$ 再估算 |
| 枚举所有排列 | $n!$ | 通常先考虑 $n\le10$;若每个方案都要逐项处理或输出,范围还需缩小 |
| 三层各枚举 n 次 | $n^3$ | 通常先考虑 $n\le200$,此时约八百万次简单操作 |
| 枚举所有数对 | $n^2$ | 通常先考虑 $n\le3000$;循环体很简单且时间允许时,可再评估到约 5000 |
| 排序 | $n\log n$ | 普通整数排序通常可考虑 $n\le10^6$ |
| 一次遍历、前缀和 | $n$ | 简单线性处理通常可考虑 $n\le10^7$,还要确认输入量与内存是否允许 |
例如 n 的上限是十万,枚举所有数对会达到百亿量级,就要想办法用排序、前缀和等方法减少重复计算。若 n 只有 20,直接枚举各种选择也可能跑得完,指数级搜索就值得考虑。
估算时别漏掉外层调用:一次判断扫描 n 个数,二分又调用多次,两部分的工作量就要相乘。内存也要一起算,二维数组的总元素个数是两维相乘,两边看着都不大,乘起来也可能占用很多空间。
## 四、枚举与模拟
### 1. 枚举
数据范围允许时,可以把可能的情况逐个检查,这就是枚举。写循环前,先确定枚举的对象和范围,再把题目的合法条件放进去。
#### 例:统计和为目标值的数对
给定 n 个整数和目标值 target,统计有多少对不同位置的元素之和等于 target。同一对位置只算一次,交换两个位置的顺序不产生新方案。
这道题枚举的是两个位置。让第二个位置始终在第一个位置之后,就能排除同一个位置,也避免交换顺序后重复计算:
```cpp
long long ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
if (a[i] + a[j] == target) ans++;
}
}
```
代码中让 `j` 从 `i+1` 开始,因此 `(i,j)` 和 `(j,i)` 只会统计其中一对。
题目说“两个数”时,要分清是在选两个位置,还是选两个不同数值。相同数值出现在不同位置,是否可以同时选,要由题意决定。
对于暂时想不到优化方法得题目,可以先写出小范围暴力。之后优化时,用它核对结果;比赛中也可能拿到对应数据范围的分数,具体得分要看测试点或子任务如何组织。
### 2. 模拟
模拟题直接按照题目规则执行即可,但要注意题目得操作要求/顺序,看看应该先判断还是先修改,改过的值会不会影响本轮后面的判断。例如装物品不能超重,就应先检查加入后的总重量,再决定是否加入。
如果题目规定“同时发生变化”,就要先保留旧状态,再统一更新。否则边扫描边修改时,后面的位置可能读到本轮刚改过的新值,执行出来就和题意不同了。
举个简单例子:在一排格子中,每一轮让中间各格的数变成左右相邻两格的数之和,两端保持不变,所有格子同时变化。例如原来的数是:`1 2 3 4`。
如果直接从左往右修改原数组:
```cpp
for (int i = 1; i < n - 1; i++) {
a[i] = a[i - 1] + a[i + 1];
}
```
第二格先变成了 4。接下来计算第三格时,读到的第二格已经是新值,于是算成 `4 + 4 = 8`,最终得到:`1 4 8 4`
这就不符合“同时变化”的要求了。正确做法是用另一个数组保存本轮结果,**始终从旧数组读取,向新数组写入**,这样,计算第三格时读取的仍是旧值 2,不会受到第二格新值的影响。
## 五、排序与贪心
### 1. 排序
当原有顺序不影响答案时,可以考虑先排序,让大小关系变得清楚。常用的升序写法如下:
```cpp
sort(a + 1, a + n + 1); // 排序 a[1] 到 a[n]
sort(v.begin(), v.end()); // 排序整个 vector
```
`sort` 的范围是左闭右开:包含第一个参数指向的位置,不包含第二个参数指向的位置。要排序下标 1~n,就把右端写成 `a+n+1`;少写这个 `+1`,最后一个元素就没有参与排序。
#### 例:按成绩和编号排序
给定若干学生的成绩与编号,要求按成绩从高到低排列;成绩相同的,编号较小者在前。那么就要自己书写比较函数:
```cpp
struct Student { int score, id; };
bool cmp(const Student& a, const Student& b) {
if (a.score != b.score) return a.score > b.score;
return a.id < b.id;
}
sort(v.begin(), v.end(), cmp);
```
这个比较函数先看成绩,成绩相同才看编号。比较时使用严格的先后关系,不能写成 `a.score >= b.score`;两个元素完全相同时,比较结果应为假。
整数的取值范围很小时,也可以先用计数数组记录出现次数,再按数值顺序输出。但是开数组前要看值域有多大,值太大就不适合直接作为数组下标。
### 2. 贪心算法
有些题排序之后,还需要决定按什么规则选择,这时可以考虑贪心。它在每一步作出选择,因此需要说明:这一步选完,为什么仍能得到整体最优的结果?
#### 例:安排尽可能多的活动
给定若干活动的开始、结束时间,选择尽可能多的互不冲突活动,求最多能选几个。本例允许一个活动结束时,下一个活动立刻开始,且活动时长为正。
先按结束时间从小到大排序,每次选择当前能接上的活动。
结束得越早,留给后面的时间越多。把最优方案中第一个活动换成结束最早的可选活动,后面的活动仍然接得上;之后对剩余活动继续这样选择,就有了这个策略的依据。
```cpp
int count = 0, last = 0; // 此处约定区间起点均不小于 0
for (int i = 1; i <= n; i++) {
if (seg[i].l >= last) {
count++;
last = seg[i].r;
}
}
```
## 六、前缀和与差分
### 1. 前缀和
同一个数组上反复求区间和,每次从头相加会做很多重复工作。可以先记下前面各项的总和:令 `s[i]` 表示前 i 个数的和,`s[0]=0`,逐项累加得到 $s[i]=s[i-1]+a[i]$。
查询闭区间时,去掉左端点之前的部分:$\operatorname{sum}(l,r)=s[r]-s[l-1]$。
```cpp
vector<long long> s(n + 1, 0);
for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];
// 查询闭区间 [l,r]:s[r] - s[l - 1]
```
例如数组为 2、−1、4、3,要查询第 2~4 项的和。前缀和依次为 0、2、1、5、8,因此区间 `[2,4]` 的和是 `8-2=6`。去掉的是第 l 项之前的部分,所以减 `l-1` 对应的前缀和。
预处理扫描一遍,之后每次查询只做一次减法。它适合数组不变、查询很多的情况;原数组修改后,旧前缀和也可能失效。
### 2. 差分
如果题目要反复给一段数反复执行区间修改得操作,那么可以记录相邻元素的差,把整段修改变成两个位置的修改。这里从下标 0 开始:定义 `d[0]=a[0]`,对于 `i>=1`,令 `d[i]=a[i]-a[i-1]`。把这些差从头累加,就能还原原数组。
给闭区间 `[l,r]` 全部加 x,只改两处:
```cpp
d[l] += x;
d[r + 1] -= x;
```
还原时,增量从 `l` 处开始生效,到 `r+1` 处被抵消,所以中间整段都会增加 x。等全部修改完成后,再统一求前缀和,得到最终数组:
```cpp
long long value = 0;
for (int i = 0; i < n; i++) {
value += d[i];
a[i] = value;
}
```
## 七、二分
### 1. 二分查找
给定升序数组和目标值 x,找到第一个大于或等于 x 的元素下标;如果不存在,就返回 `n+1`。
由于数组 `a[1..n]` 已经升序排列,小于 x 的元素都在前面,不小于 x 的都在后面,两部分之间只有一道分界。每次检查中间位置,就能确定接下来该往哪一半找。
```cpp
int l = 1, r = n, ans = n + 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (a[mid] >= x) {
ans = mid; // 先记下这个满足条件的位置
r = mid - 1; // 再去左边找更靠前的位置
} else {
l = mid + 1;
}
}
// ans==n+1 表示不存在,否则 ans 就是所求位置
```
当 `mid` 满足条件,先把它记进 ans,再去左半边找更靠前的位置;不满足时,就去右半边。ans 始终留着已经找到的结果,后面只有找到更早的位置时才替换它。
例如数组为 `2 4 4 7`,查找第一个不小于 4 的位置,最终得到 ans=2。要判断 x 是否确实存在,可以检查 `ans <= n && a[ans] == x`,先确认下标合法,再读取元素。
这里使用闭区间 `[l,r]`,循环条件是 `l <= r`。检查过 mid 后,用 `mid-1` 或 `mid+1` 缩小范围,不再重复检查这个位置。
### 2. 二分答案
二分也可以用来找最优答案。先尝试一个值,判断它能否满足要求;如果可行与不可行之间只有一道分界,就可以不断缩小答案范围。
#### 例:分段的最大段和
给定一个包含 n 个正整数的序列,以及一个正整数 k,其中 $1\le k\le n$。请在不改变元素顺序的前提下,将整个序列分成不超过 k 个非空连续段。每个元素必须恰好属于其中一段,不能遗漏或重复使用。
对于一种分段方案,先分别计算每一段的元素之和,再取这些段和中的最大值,作为该方案的结果。请找到一种分段方案,使这个最大值尽可能小,并输出它的最小值。例如,序列为 `7 2 5 10 8`,k=2。若分成 `7 2 5` 和 `10 8` 两段,段和分别为 14、18,最大段和为 18。其他合法方案都无法让最大段和小于 18,因此答案为 18。
那么就可以假设允许的最大段和是 `limit`,可以从左到右尽量往当前段加入元素,装不下就新开一段。如果这样需要的段数不超过 k,就说明这个上限可行。
分析题目发现,如果上限越大,限制越宽松:某个值已经可行,更大的值也可行。存在着单调性,因此可以二分“第一个可行值”。
确定了单调性,再找搜索范围。一个元素不能拆开,所以答案至少是最大元素;把整串作为一段,则得到总和这个上界。代码中用 `a[1..n]` 保存正整数,约定 `1<=k<=n`,相关变量已准备好。
先写判断函数,看看上限 limit 是否能让段数不超过 k:
```cpp
bool check(long long limit) {
int count = 1;
long long sum = 0;
for (int i = 1; i <= n; i++) {
if (a[i] > limit) return false;
if (sum + a[i] > limit) {
count++;
sum = a[i];
} else {
sum += a[i];
}
}
return count <= k;
}
```
再记录已经找到的可行答案,继续尝试更小的上限:
```cpp
long long l = 0, r = 0;
for (int i = 1; i <= n; i++) {
l = max(l, (long long)a[i]);
r += a[i];
}
long long ans = r;
while (l <= r) {
long long mid = l + (r - l) / 2;
if (check(mid)) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
// ans 是最大段和能达到的最小值
```
`check(mid)` 为真,说明 mid 能用,先存下来,再向左找;为假,说明上限太小,就向右找。
对于题目出现需要求“最大的最小”的时候,就可以确认单调性,再决定是否通过二分去解决。
## 八、栈、队列与搜索
### 1. 栈
栈只在一端放入、取出元素,这一端叫栈顶。像一摞盘子,通常先取走最上面、也就是最后放上去的那个。
依次压入 2、5、7,此时栈顶是 7;弹出一次后,栈顶变成 5,再弹出才轮到 2。这就是“后进先出”。
| 操作 | `stack<int> st` 的写法 | 要记住的事 |
| --- | --- | --- |
| 压入元素 | `st.push(x)` | x 成为新栈顶 |
| 读取栈顶 | `st.top()` | 只读取,不删除 |
| 弹出栈顶 | `st.pop()` | 只删除,不返回元素 |
| 判断是否为空 | `st.empty()` | 空栈不能读取或弹出 |
| 元素个数 | `st.size()` | 表示当前还留在栈中的数量 |
需要取出并保存栈顶时,先读再删:
```cpp
if (!st.empty()) {
int x = st.top();
st.pop();
// 使用 x
}
```
#### 例:判断括号是否匹配
给定一个只包含 `(`、`)`、`[`、`]` 的字符串,判断括号能否按正确的类型和嵌套顺序全部配对。
右括号要先和最近一个尚未配对的左括号匹配,这正好符合栈的顺序。遇到左括号就入栈,遇到右括号就检查栈顶。
例如 `([])`:先压入 `(`,再压入 `[`;遇到 `]` 时,配对并弹出 `[`;遇到 `)` 时,再弹出 `(`。处理完后栈为空,匹配成功。
`([)]` 则在读到 `)` 时出错:栈顶是 `[`,类型对不上,也不能越过它去找更下面的 `(`。
```cpp
bool matched(const string& s) {
stack<char> st;
for (char c : s) {
if (c == '(' || c == '[') {
st.push(c);
} else {
if (st.empty()) return false;
char t = st.top();
if ((c == ')' && t != '(') ||
(c == ']' && t != '[')) return false;
st.pop();
}
}
return st.empty();
}
```
除了中途检查空栈和括号类型,结束时还要确认栈为空。比如 `(()` 中途没有冲突,却留下了一个左括号,所以函数最后还要判断一次是否配完。
撤销最近一次操作、处理嵌套结构时,也常会用到栈。递归调用有类似的返回顺序:后调用的那一层先执行完,再回到调用它的位置。
### 2. 队列
队列在队尾加入元素,在队首取出元素。依次加入 2、5、7,处理顺序就是 2、5、7,这叫“先进先出”。
| 操作 | `queue<int> q` 的写法 | 要记住的事 |
| --- | --- | --- |
| 入队 | `q.push(x)` | 加在队尾 |
| 读取队首 | `q.front()` | 取得下一个待处理元素 |
| 读取队尾 | `q.back()` | 取得最后加入的元素 |
| 出队 | `q.pop()` | 删除队首,不返回元素 |
| 判断是否为空 | `q.empty()` | 读队首、队尾或出队前确认非空 |
| 元素个数 | `q.size()` | 当前队列长度 |
#### 例:循环报数
编号 1~n 的人围成一圈,从 1 开始报数,报到 k 的人出队,再从下一个人重新报 1。要求输出所有人的出队顺序,其中 n、k 均为正整数。
可以把围成一圈的报数过程放进队列:没数到 k 的人先移到队尾,报到 k 的人输出后删除。比如 1、2、3、4、5 每次数到第 3 人出队,就先移动前两个人,再删除当前队首。
```cpp
queue<int> q;
for (int i = 1; i <= n; i++) q.push(i);
while (!q.empty()) {
for (int i = 1; i < k; i++) {
int x = q.front();
q.pop();
q.push(x);
}
cout << q.front() << ' ';
q.pop();
}
```
`n=5`、`k=3` 时,出队顺序为 `3 1 5 2 4`。每轮只移动 k−1 次,紧接着的队首才是第 k 人,多移动一次就会错位。
这份写法的操作次数约为 $nk$,适合规模允许时使用。k 很大时,要留意反复移到队尾的开销。
按到达顺序办理任务,也可以用队列。BFS 就借助队列,让早发现、距离近的状态先被处理。
### 3. DFS 与回溯
如果每一步都有几种选择,可以沿着一种选择继续尝试,走到完成方案或无法继续时,再返回尝试其他选择,这就是 DFS 的过程。分支层数随输入变化时,用递归比写很多层固定循环更方便。
回溯中最容易漏掉的是恢复现场:如果这一步修改了后续分支共用的路径或标记,返回后要记得撤销修改。
#### 例一:选数凑目标和
给定 n 个整数和目标和 target,每个位置最多选一次,统计选出的数之和等于 target 的方案数。按位置区分选法,允许空集。
例如三个数为 2、3、5,目标和为 5,有两种选法:选 2 和 3,或者只选 5。
处理一个位置时,只有“选”和“不选”两个分支。可以进行搜索,令 `dfs(pos, sum)` 表示前面的位置已经决定完,现在处理第 pos 个数,当前和为 sum。
```cpp
int n;
long long target, ans = 0;
vector<long long> a; // 使用 a[1..n]
void dfs(int pos, long long sum) {
if (pos == n + 1) {
if (sum == target) ans++;
return;
}
sum += a[pos]; // 选当前位置
dfs(pos + 1, sum);
sum -= a[pos]; // 恢复本层的和,再尝试不选
dfs(pos + 1, sum);
}
// 读入数据、令 ans=0 后,调用 dfs(1, 0)
```
等每个位置都决定完,再检查和是否等于目标,这样一组选择只会统计一次。若题目要求至少选一个数,还要记录是否已经选择过元素。
代码先把当前数加进本层的 sum,试完“选”的分支后再减回来,接着尝试“不选”。下一层按值接收参数,对它自己局部变量的修改不会传回本层。另一种写法是直接传入 `sum + a[pos]`,这样本层的和没有改变,就省去了加减操作。
如果还要记录具体选了哪些数,可以用数组或 `vector` 保存路径:选时加入,递归回来后删掉。n 个位置各有两种选择,总方案数为 $2^n$,只能用于较小规模。所有数非负时,和超过目标后可以停止该分支;有负数时,后面可能把和减回来,不能这样剪枝。
#### 例二:选数组合
从整数 1~n 中选出 k 个不同的数,输出所有组合,每个组合只输出一次。这里约定 `1≤k≤n`,组合内部按递增顺序输出。
例如从 1、2、3、4 中选两个数,`1 3` 和 `3 1` 是同一种组合。让选出的数字始终递增,就只会生成一次。
```cpp
int n, k;
vector<int> path;
void choose(int start) {
if (path.size() == k) {
for (int x : path) cout << x << ' ';
cout << '\n';
return;
}
for (int x = start; x <= n; x++) {
path.push_back(x);
choose(x + 1);
path.pop_back();
}
}
// 约定 1<=k<=n,初始路径为空,调用 choose(1)
```
代码用 `start` 限定下一次可选的最小值。选了 2,下一层就从 3 开始,既不会重复选 2,也就不会回头产生顺序颠倒的组合,因此不用额外记录哪些数已经用过。
与前一个例子的局部和不同,`path` 是各层递归时共用的,所以它是一个全局变量,那么 加入后尝试深入 和 回溯后撤销 的操作就要配套:`push_back` 记录选择,返回后用 `pop_back` 撤销。比如试完 `1 2`,退回到路径只含 1 的状态,才能接着试 `1 3`。
#### 例三:迷宫路径计数
给定一个网格、起点和终点,只能上下左右移动,不能经过障碍,也不能在同一条路径中重复经过格子。求满足这些条件的路径总数。
因为每一步都可以尝试向上、下、左、右移动,因此可以用递归搜索:先决定当前这一层处理所在的格子,然后递归到下一层处理准备走到的相邻格子。如果到达终点,就说明找到了一条完整路径,将答案加 1,并结束这条分支,不再从终点继续走。不过尝试一个方向之前,要先检查下一格是否在网格范围内、是否为障碍,以及是否已经在当前路径中经过。只有这三个检查都通过,才能继续递归。
且为了避免同一条路径重复经过格子,进入一个格子时,要把它标记为“已经经过”。例如从起点向右走了一格,这一格就加入了当前路径;接下来继续搜索时,不能再走回它。
当这个格子后面的所有走法都尝试完,就要返回上一层,并取消它的访问标记。因为题目限制的是“同一条路径不能重复经过格子”,其他路径仍然可以经过这里。如果返回时不取消标记,后续路径就可能被错误地拦住,导致少算。
因此,整个搜索过程可以理解为:**进入格子并标记,尝试四个方向,搜索结束后取消标记,再返回上一层。** 每次返回,都恢复到进入这一格之前的状态,方便继续尝试其他走法,这个过程就叫作回溯。
下面约定行列从 0 开始,`grid` 是全局字符串数组,`'#'` 表示障碍;`vis` 大小为 n×m,初始全为 0,起终点均合法且可通行:
```cpp
int n, m, tx, ty;
long long ways = 0;
vector<string> grid;
vector<vector<int>> vis;
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
void walk(int x, int y) {
if (x == tx && y == ty) {
ways++;
return;
}
vis[x][y] = 1;
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) continue;
if (grid[nx][ny] == '#' || vis[nx][ny]) continue;
walk(nx, ny);
}
vis[x][y] = 0;
}
// ways=0,vis 清零后,调用 walk(sx, sy)
```
如果把最后的恢复语句删掉,某条路径走过的格子会挡住其他路径,统计就可能漏掉。相反,在同一条路径还没结束时就取消标记,又会允许绕圈重复进入。
### 4. BFS
BFS 改用队列安排访问顺序,先处理距离起点近的状态,再处理更远的状态。它适合无权图或每一步代价相同的最少步数问题;当边权不同时,就不能直接沿用这种最短路判断。
一层里的点处理完,才轮到下一层,所以第一次发现一个点时,就已经找到了到达它的最少边数。
#### 例:求无权图中的最少步数
给定一个无权图和起点 s,求从 s 到各点最少经过多少条边;不可达的点记为 −1。
通过邻接表 `g[u]` 保存 u 的邻居,`dist` 长度为 `n+1` 且全部初始化为 `-1`:
```cpp
queue<int> q;
dist[s] = 0;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : g[u]) {
if (dist[v] != -1) continue;
dist[v] = dist[u] + 1;
q.push(v);
}
}
```
代码在入队时设置距离,同时完成访问标记,因此同一个点不会被反复加入队列。起点距离为 0,不可达的点则一直保持 −1,两者含义不同。
对于二维网格中的 BFS 也是同样的过程,只是一个状态改成行、列。扩展邻格时,需要依次检查:坐标合法、不是障碍、尚未访问。
### 6. 图的存储与连通块
前面的 BFS 通过邻居列表查找下一步能到哪里。存图时,邻接表只记录实际存在的边,通常适合边较少的图;邻接矩阵则直接记录两点是否相连,查边方便,但空间约为点数的平方。
无向边 `u-v` 用邻接表存储时,通常要加入两个方向。遍历无向图时必须防止沿边反复返回,使用访问标记,或在确实为树的条件下跳过父节点。
统计连通块时,从每个尚未访问的点开始一次 DFS 或 BFS,每次新启动的遍历对应一个新连通块。网格中的连通区域也可以这样做,这就是常见的泛洪填充。
## 九、动态规划
### 1. 一维 DP
#### 例:爬台阶
有 n 级台阶,每次可以上 1 级或 2 级,求恰好走到第 n 级的不同走法数。步子的先后顺序不同,算不同走法。
令 `dp[i]` 表示恰好到达第 i 级的方法数。
考虑最后一步:要么从第 i−1 级走 1 级,要么从第 i−2 级走 2 级。两种走法不会重复,加起来就是 $dp[i]=dp[i-1]+dp[i-2]$。
起点设为 `dp[0]=1`,表示“还没走”这一种起始方案,另外有 `dp[1]=1`。接着从小到大计算,每次用到的前两项都已经算好。
走法数增长很快,要估计结果范围。可以先考虑 `long long`,但它也有上限;题目要求取模时,应在递推过程中及时取模,而不能只对结果取模。
### 2. 最长上升子序列
给定一个数组,可以删去一些元素,但保留剩余元素的相对顺序,求严格上升子序列的最大长度。
这次把终点固定在第 i 个数:令 `dp[i]` 表示“以第 i 个数结尾的最长严格上升子序列长度”。它前面可以接上一个位置更早、数值更小的元素,因此逐个尝试前面的 j。初值设为 1,表示只选当前这个数。
```cpp
int ans = 0;
for (int i = 1; i <= n; i++) {
dp[i] = 1;
for (int j = 1; j < i; j++) {
if (a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1);
}
ans = max(ans, dp[i]);
}
```
最长的那一段子序列可能在任何位置结束,所以答案要取所有 `dp[i]` 的最大值,不能只看 `dp[n]`。严格上升用 `<`,允许相等的不下降版本才使用 `<=`。
子序列可以跳过元素,连续子数组则不能。读题时先分清这两个要求。上面写法的工作量为平方级,使用前要看 n 的范围。
### 3. 0/1 背包
给定容量 V 和 n 件物品,第 i 件的体积为 `w[i]`、价值为 `v[i]`。每件最多选一次,求总体积不超过 V 时的最大总价值,允许一件也不选。
令 `dp[j]` 表示已考虑的物品中,总体积不超过 j 时的最大价值。
初始全为 0,表示还没选物品。处理当前物品时,不拿就保留原来的最大价值;拿一次,就从扣除当前体积后的状态转移过来,再加上它的价值:
```cpp
vector<long long> dp(V + 1, 0);
for (int i = 1; i <= n; i++) { // 考虑前 i 件物品
for (int j = V; j >= w[i]; j--) { // 考虑前 i 件物品的情况下,背包容量为 j 时能获得的最大价值
dp[j] = max(dp[j], dp[j - w[i]] + v[i]); // 对于第 i 件物品,要么拿,要么不拿取最大值
}
}
```
这里的容量从大到小更新。计算 `dp[j]` 时,较小容量的 `dp[j-w[i]]` 还没被本件物品更新,用的仍是上一轮结果(考虑前 i - 1 件物品的情况下,背包容量为 j 时能获得的最大价值),因此每件物品只会选一次。
如果从小到大更新,刚刚拿过本件物品的状态就可能再次参与转移,相当于又拿了一次。这正是下一种背包允许的情况。
答案为 `dp[V]`。
### 4. 完全背包
给定容量 V 和 n 种物品,每种体积为正、数量不限,求总体积不超过 V 时的最大总价值。
每种物品既然可以重复选择,就允许继续使用本轮已经更新过的状态(考虑前 i 件物品的情况下,背包容量为 j 时能获得的最大价值),而这个已经被更新过的状态就有可能已经拿了第 i 件物品了,符合可以重复拿取的定义,那么沿用上一节的状态定义,把容量改为正序枚举即可:
```cpp
for (int i = 1; i <= n; i++) {
for (int j = w[i]; j <= V; j++) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
```
记不清循环方向时,可以思考依赖的来源状态:它必须来自上一轮,还是允许本轮重复使用?
## 十、数学与位运算
### 1. 最大公约数与最小公倍数
求两个非负整数的最大公约数,可以反复用“除数、余数”替换当前两个数,直到余数为 0。这样做不会改变最大公约数。
```cpp
long long gcd(long long a, long long b) { // a、b 非负
while (b != 0) {
long long r = a % b;
a = b;
b = r;
}
return a;
}
```
求出最大公约数后,还可以用它计算正整数 a、b 的最小公倍数 lcm:
$$\operatorname{lcm}(a,b)=\frac{a}{\gcd(a,b)}\times b$$
### 2. 质数判断与因数分解
判断一个整数 n 是否为质数,先排除小于 2 的数,再尝试 2 到平方根之间的除数。只要找到一个能整除它的数,就可以确定它是合数:
```cpp
bool isPrime(int n) {
if (n < 2) return false;
for (int d = 2; 1LL * d * d <= n; d++) {
if (n % d == 0) return false;
}
return true;
}
```
循环条件保留等号,才能检查到 9、25 这样的完全平方数的平方根。需要判断很多个数时,可以考虑筛法,减少反复试除的工作。
同样的试除思路也能用来分解质因数:找到一个因数后,反复除尽,并记录除过几次。剩余数变小,试除范围也随之缩小;结束时若还剩一个大于 1 的数,它本身就是一个质因数。
### 3. 位运算
位运算处理的是整数的二进制位。先把数位对齐,再对同一位置上的 0、1 分别计算。例如 5 写成 `101`,3 写成 `011`,就可以按下面的规则逐位运算。
| 运算 | 每一位的规则 | 例子 |
| --- | --- | --- |
| 按位与 `&` | 两位都是 1,结果才是 1 | `5 & 3` 得到 `001`,即 1 |
| 按位或 `|` | 两位至少有一个 1,结果就是 1 | `5 | 3` 得到 `111`,即 7 |
| 按位异或 `^` | 两位不同得 1,相同得 0 | `5 ^ 3` 得到 `110`,即 6 |
| 按位取反 `~` | 每一位的 0、1 互换 | 对类型的全部位取反,不只处理写出来的几位 |
| 左移 `<<`、右移 `>>` | 把二进制位向左或向右移动 | 对非负整数,`5 << 1` 为 10,`5 >> 1` 为 2 |
左移时低位补 0;非负整数右移时高位补 0,移出的低位丢弃。移位次数必须在类型允许范围内,左移后的值也要能表示。
这些规则可以用来检查某一位。`x & 1` 只看最低位,结果为 1 就是奇数;`(x >> k) & 1` 先把第 k 位移到最低位,再取出它,最低位编号为 0。异或还满足两个常用性质:相同数异或为 0,一个数与 0 异或仍是它自己。
`^` 表示异或,不是乘方。若只有一个数出现奇数次,其余数都出现偶数次,把所有数异或起来,相同的数会两两抵消,最后就剩下那个数。
## 十一、高精度运算
整数超过 `long long` 的范围时,可以用字符串保存,按照手算竖式的规则逐位计算。下面的输入均为非负整数,减法结果可以为负数。
### 1. 数位存储
按平常写数的顺序保存,例如 5079 存成字符串“5079”。计算前去掉多余前导零,全为零时保留一个 0。
加、减、乘法可以先反转字符串,让下标 0 对应个位、下标 1 对应十位,算完后再反转结果。除法从最高位开始,不需要反转。
字符串中存的是字符,参与计算时要转成对应数字,算出的数位再转回字符保存。
### 2. 高精度加法
要求计算两个非负大整数的和。
1. 反转两个字符串,在较短串末尾补零,使对应数位对齐。
2. 从个位开始,将两个对应数位与上一位的进位相加。
3. 总和除以 10 的余数作为本位,整数商作为下一位的进位。
4. 所有数位算完后,若仍有进位,就追加到结果末尾,最后反转结果。
例如 $999+1$,每一位都会产生进位,原有数位算完后还要补上最高位的 1,得到 1000。
### 3. 高精度减法
要求计算两个非负大整数的差,结果可以为负数。
1. 先比较大小:去掉前导零后,位数多的更大;位数相同,从最高位开始比较第一个不同的数位。
2. 若被减数较小,交换两数并记录负号,之后用较大的数减较小的数。
3. 反转两个字符串,给较短串末尾补零。从个位开始,计算对应数位的差,再扣除上一位的借位。
4. 本位不够减时加 10,并向更高位借 1;下一轮计算要扣掉这次借位。
5. 去掉倒序结果末尾的多余零,至少保留一位,再反转结果,按需添加负号。
例如 $1000-1=999$,要连续借位;$1-1000=-999$,先算差的绝对值,再加负号。两数相等时结果为 0。
### 4. 高精度乘法
要求计算两个非负大整数的积,采用“先累加乘积,再统一进位”的方法。
1. 任意一个数为 0,结果直接为 0。否则反转两个字符串,让下标 0 对应个位。
2. n 位数乘 m 位数,积最多 n+m 位,准备这么多个位置的整数数组,初值全为 0。
3. 每一对数位分别相乘,第 i 位与第 j 位的乘积累加到第 i+j 位,暂不进位。同一位置会收到多个乘积,累加值可以大于 9。
4. 从低位到高位统一进位:当前累加值加上上一位的进位,除以 10 的余数作为本位,整数商继续向高位传递。
5. 处理完剩余进位,去掉倒序结果末尾的多余零,再反转结果。
例如 $23\times47$,个位先累加 $3\times7=21$,十位累加 $3\times4+2\times7=26$,百位累加 $2\times4=8$。统一进位后,个位留 1、进 2,十位得到 28、留 8、进 2,百位得到 10、留 0、进 1,最终得到 1081。
两组数位分别遍历,时间复杂度为 $O(nm)$。
### 5. 高精度除以小整数
要求用非负大整数除以正整数 b,求整数商和余数。大整数用字符串保存,b 能放进 `int`。
手算除法时,先看前面的数够除几次,再留下余数、落下下一位。因此字符串也从最高位开始,向右逐位计算。
1. 余数初始为 0,从左到右依次读取数位。
2. 把上一轮余数乘 10,再加上当前数位,组成这一轮待除的数。
3. 用它除以 b,整数商作为当前一位商,余数留给下一轮。
4. 全部数位处理完后,只去掉商开头多余的零,中间的零必须保留。最后留下的余数就是最终余数。
例如计算 1234 除以 12:
| 读入数位 | 上轮余数乘 10,再加当前位 | 本位商 | 新余数 |
| --- | --- | --- | --- |
| 1 | $0\times10+1=1$ | 0 | 1 |
| 2 | $1\times10+2=12$ | 1 | 0 |
| 3 | $0\times10+3=3$ | 0 | 3 |
| 4 | $3\times10+4=34$ | 2 | 10 |
依次得到 0102,去掉开头多余的零,商为 102,余数为 10。商十位上的 0 不能省略,结果满足 $1234=12\times102+10$。
被除数小于 b 时,商为 0,余数为被除数;被除数为 0 时,商和余数均为 0。余数乘 10 的中间值可能超出 `int`,要用 `long long` 保存。整个过程扫描一次字符串,时间复杂度为 $O(n)$。
## 十二、树
### 1. 树的基本概念
树是连通且没有环的无向图。n 个节点的树有 n−1 条边,任意两个不同节点之间只有一条不重复经过节点的路径。
给树选定一个根后,就可以从根往下确定父子关系。下图以 1 为根:
<img src="C:\Users\xiaolinquan\AppData\Roaming\Typora\typora-user-images\image-20261016220317516.png" alt="image-20261016220317516" style="zoom:40%;" />
| 名称 | 怎样理解 | 图中的例子 |
| --- | --- | --- |
| 根节点 | 选定的起点,没有父节点 | 1 |
| 父节点、子节点 | 相邻两点中,靠近根的是父,远离根的是子 | 2 是 4、5 的父节点 |
| 兄弟节点 | 具有同一个父节点 | 4 和 5 |
| 叶节点 | 有根树中没有子节点的节点 | 4、5、6、7 |
| 子树 | 一个节点和它的全部后代构成的树 | 以 2 为根的子树含 2、4、5 |
| 深度 | 从根到该节点经过的边数,根深度为 0 | 2 的深度为 1,4 的深度为 2 |
例如,节点 5 的深度为 2,以 2 为根的子树包含 2、4、5。这里根的深度为 0;有些题目把根所在层记为第 1 层,要注意区分。
### 2. 树的几种存储方式
树可以用编号和数组、邻接表或动态节点保存。本节重点掌握动态创建节点的方法,前两种方式了解基本形式即可。
#### 用编号和数组保存二叉树
二叉树的每个节点最多有两个孩子,按编号保存时,可以用结构体数组记录左右孩子:
```cpp
struct TreeNode {
int left;
int right;
};
TreeNode tree[8] = {}; // 下标 1~7 对应节点,初值全为 0
tree[1].left = 2; tree[1].right = 3;
tree[2].left = 4; tree[2].right = 5;
tree[3].left = 6; tree[3].right = 7;
```
数组下标表示节点编号,`left`、`right` 保存孩子编号,0 表示没有孩子。例如 `tree[2].right` 的值为 5,表示节点 2 的右孩子是 5。
#### 用邻接表保存相邻关系
普通树可以用邻接表保存相邻节点。`neighbors[node]` 保存与 node 直接相连的节点。无向边要在两端各保存一次:
```cpp
vector<vector<int>> neighbors(n + 1);
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
neighbors[u].push_back(v);
neighbors[v].push_back(u);
}
```
### 3. 动态创建节点
动态存储时,用结构体保存节点的值和两个孩子的地址,需要新节点时用 `new` 创建,再连接到树上。
以二叉树为例,一个节点可以这样定义:
```cpp
struct Node {
int value;
Node* left;
Node* right;
};
```
`value` 保存节点的值,`left`、`right` 指向左右孩子,`nullptr` 表示没有孩子。创建根节点:
```cpp
Node* root = new Node{1, nullptr, nullptr};
```
`new` 返回新节点的地址,`root` 保存这个地址。创建并连接左孩子:
```cpp
Node* child = new Node{2, nullptr, nullptr};
root->left = child;
```
`->` 用来通过指针访问成员。也可以直接写成 `root->left = new Node{2, nullptr, nullptr};`。
#### 例一:动态建立一棵二叉树
按上面的二叉树图创建 7 个节点,并输出节点 5 的值:
```cpp
Node* root = new Node{1, nullptr, nullptr};
root->left = new Node{2, nullptr, nullptr}; root->right = new Node{3, nullptr, nullptr};
root->left->left = new Node{4, nullptr, nullptr};
root->left->right = new Node{5, nullptr, nullptr};
root->right->left = new Node{6, nullptr, nullptr};
root->right->right = new Node{7, nullptr, nullptr};
cout << root->left->right->value; // 输出 5
```
`root->left->right->value` 表示根的左孩子的右孩子的值,也就是节点 5 的值。但是访问成员前,要保证前面的指针不是 `nullptr`。
### 4. 二叉树的遍历
常见的二叉树遍历如下:
| 遍历方式 | 处理顺序 |
| --- | --- |
| 前序 | 根、左子树、右子树 |
| 中序 | 左子树、根、右子树 |
| 后序 | 左子树、右子树、根 |
#### 例二:遍历动态建立的二叉树
对例一建立的二叉树,前序序列为 `1 2 4 5 3 6 7`。前序遍历如下:
```cpp
void preOrder(Node* node) {
if (node == nullptr) return;
cout << node->value << ' ';
preOrder(node->left);
preOrder(node->right);
}
// 建好树后调用 preOrder(root),输出 1 2 4 5 3 6 7
```
中序序列为 `4 2 5 1 6 3 7`,把输出语句放在两次递归之间;后序序列为 `4 5 2 6 7 3 1`,把输出语句放在两次递归之后。空指针要先判断。
层序遍历使用队列,输出顺序为 `1 2 3 4 5 6 7`。
@@ -0,0 +1,150 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.1 进制转换 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | D | C | B | C | B | B | B | B | 101 | B |
| 题号 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | A | C | B | B | $(0.101)_2$ | A | 0.75 | B | A |
| 题号 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | $(111111.1)_2$ | B | $(1\text{E}5)_{16}$ | C | C | B | 45 | B | B |
| 题号 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | C | 5 | A | 4 | B | B | C | B | 4 |
---
### 详细解析
#### 题型一:位权与数码规则
1. **答案:D**
七进制数的基数为 7,允许使用的数码是 $0 \sim 6$,因此 $7$ 是不允许出现的。
2. **答案:C**
五进制数允许使用的数码是 $0 \sim 4$。选项 C 中的 $(5104)_5$ 包含了数码 $5$,因此不合法。
3. **答案:B**
$(101101)_2 = 1 \times 2^5 + 0 \times 2^4 + 1 \times 2^3 + 1 \times 2^2 + 0 \times 2^1 + 1 \times 2^0 = 32 + 8 + 4 + 1 = 45$。
4. **答案:C**
$(347)_8 = 3 \times 8^2 + 4 \times 8^1 + 7 \times 8^0 = 3 \times 64 + 32 + 7 = 192 + 32 + 7 = 231$。
5. **答案:B**
$(2\text{AF})_{16} = 2 \times 16^2 + 10 \times 16^1 + 15 \times 16^0 = 2 \times 256 + 160 + 15 = 512 + 160 + 15 = 687$。
#### 题型二:整数进制转换
6. **答案:B**
$94 = 64 + 16 + 8 + 4 + 2 = 2^6 + 2^4 + 2^3 + 2^2 + 2^1 = (1011110)_2$。
7. **答案:B**
采用除 8 取余法:$156 \div 8 = 19$ 余 4;$19 \div 8 = 2$ 余 3;$2 \div 8 = 0$ 余 2。倒序排列余数得到 $(234)_8$。
8. **答案:B**
采用除 16 取余法:$1000 \div 16 = 62$ 余 8;$62 \div 16 = 3$ 余 14(十六进制中为 $\text{E}$);$3 \div 16 = 0$ 余 3。倒序得到 $(3\text{E}8)_{16}$。
9. **答案:101**
$(1100101)_2 = 2^6 + 2^5 + 2^2 + 2^0 = 64 + 32 + 4 + 1 = 101$。
10. **答案:B**
将二进制数从右向左每三位划分为一组:$(100000)_2 \rightarrow 100\ 000 \rightarrow (40)_8$。
11. **答案:B**
将二进制数从右向左每四位划分为一组,不足补前导零:$(111010111)_2 \rightarrow 0001\ 1101\ 0111 \rightarrow (1\text{D}7)_{16}$。
12. **答案:A**
将十六进制数的每一位展开为四位二进制数:$7 \rightarrow 0111$,$\text{B} \rightarrow 1011$,$4 \rightarrow 0100$。合并得 $(0111\ 1011\ 0100)_2$。
#### 题型三:小数进制转换
13. **答案:C**
$(101.101)_2 = 2^2 + 2^0 + 2^{-1} + 2^{-3} = 4 + 1 + 0.5 + 0.125 = 5.625$。
14. **答案:B**
$(17.4)_8 = 1 \times 8^1 + 7 \times 8^0 + 4 \times 8^{-1} = 8 + 7 + 0.5 = 15.5$。
15. **答案:B**
$(\text{A}.\text{C})_{16} = 10 \times 16^0 + 12 \times 16^{-1} = 10 + 12 / 16 = 10 + 0.75 = 10.75$。
16. **答案:$(0.101)_2$**
小数部分乘 2 取整法:$0.625 \times 2 = 1.25$(取 1),$0.25 \times 2 = 0.5$(取 0),$0.5 \times 2 = 1.0$(取 1)。故二进制为 $(0.101)_2$。
17. **答案:A**
整数部分:$13 = 8 + 4 + 1 = (1101)_2$;小数部分:$0.375 = 3/8 = 1/4 + 1/8 = 2^{-2} + 2^{-3} = (0.011)_2$。合并为 $(1101.011)_2$。
18. **答案:0.75**
$(0.3)_4 = 3 \times 4^{-1} = 3 / 4 = 0.75$。
#### 题型四:二、八、十六进制快速互转
19. **答案:B**
从右向左每三位分组,不足补零:$011\ 010\ 110 \rightarrow (326)_8$。
20. **答案:A**
每一位八进制数码展开为三位二进制:$5 \rightarrow 101$,$7 \rightarrow 111$,$2 \rightarrow 010$。合并为 $(101111010)_2$。
21. **答案:B**
先转为二进制:$(9\text{E})_{16} \rightarrow 1001\ 1110$;再三位分组转为八进制:$010\ 011\ 110 \rightarrow (236)_8$。
22. **答案:$(111111.1)_2$**
展开为二进制:$(3\text{F}.8)_{16} \rightarrow 0011\ 1111 . 1000$。省略前导零和末尾零后得到 $(111111.1)_2$。
23. **答案:B**
以小数点为界,向左和向右分别每四位分组,不足补零:$0010\ 1011 . 0110 \rightarrow (2\text{B}.6)_{16}$。
24. **答案:$(1\text{E}5)_{16}$**
先转二进制:$(745)_8 \rightarrow 111\ 100\ 101$;再四位分组转十六进制:$0001\ 1110\ 0101 \rightarrow (1\text{E}5)_{16}$。
#### 题型五:混合进制运算
25. **答案:C**
先将各数转为十六进制以方便运算:$(101101)_2 = (2\text{D})_{16}$,$(37)_8 = (1\text{F})_{16}$。相加:$(2\text{D})_{16} + (1\text{F})_{16} = (4\text{C})_{16}$。
26. **答案:C**
可以统一转为十进制计算:$(2\text{A})_{16} = 42$,$(1011)_2 = 11$;$42 - 11 = 31$。将 $31$ 转为八进制即 $3 \times 8 + 7 = (37)_8$。
27. **答案:B**
转为十进制:$(123)_4 = 16 + 8 + 3 = 27$,$(11)_2 = 3$;相乘 $27 \times 3 = 81$。将 $81$ 除以 4 取余得四进制表示 $(1101)_4$。
28. **答案:45**
统一转为十进制:$(1111)_2 = 15$,$(17)_8 = 15$,$(\text{F})_{16} = 15$。相加得 $15 + 15 + 15 = 45$。
29. **答案:B**
直接在二进制下做除法即可,相当于十进制中的 $16 \div 2 = 8$,对应的二进制即为 $(1000)_2$。
30. **答案:B**
转为十进制运算:$(3\text{E}8)_{16} = 3 \times 256 + 14 \times 16 + 8 = 1000$;$(1750)_8 = 1 \times 512 + 7 \times 64 + 5 \times 8 = 1000$。相加得 $2000$。$2000 \div 16 = 125$ 余 $0$,$125 \div 16 = 7$ 余 $13$($\text{D}$),得 $(7\text{D}0)_{16}$。
#### 题型六:未知进制、位数与表示范围
31. **答案:B**
根据位权展开构建方程:$1 \times b^2 + 2 \times b^1 + 1 \times b^0 = 16$,即 $(b+1)^2 = 16$,解得 $b = 3$。
32. **答案:C**
根据位权展开:$2 \times b + 3 = 17$,解得 $2b = 14$,即 $b = 7$。
33. **答案:5**
根据位权展开:$1 \times b^2 + 1 \times b + 0 = 30$,即 $b(b+1) = 30$,因为 $5 \times 6 = 30$,故基数 $b = 5$。
34. **答案:A**
观察个位数相加:$4 + 3 = 7$。但结果个位变成了 $2$,说明产生了进位,故基数 $b = 7 - 2 = 5$。代入十位数验证:$2 + 1 + 1\text{(进位)} = 4$,成立。
35. **答案:4**
十进制中 $(10000)_2 = 16$。而左侧 $(100)_b = b^2$。因此 $b^2 = 16$,解得基数 $b = 4$。
36. **答案:B**
根据位权展开方程:$5x + 2 = 17$,解得 $5x = 15$,即 $x = 3$。
37. **答案:B**
因为 $1023 = 2^{10} - 1$,即二进制下表现为 $10$ 个连续的数码 $1$,因此至少需要 $10$ 位二进制数码。
38. **答案:C**
六位三进制数的最大值为 $(222222)_3$,它恰好等于 $3^6 - 1 = 729 - 1 = 728$。
39. **答案:B**
不超过四位的十六进制数,其最大值为 $(\text{FFFF})_{16} = 16^4 - 1 = 65535$。因为题目强调是“正整数”,取值范围从 $1$ 到 $65535$,共可表示 $65535$ 个不同的正整数。
40. **答案:4**
根据带小数的位权展开方程:$1 \times b^1 + 2 \times b^0 + 1 \times b^{-1} = 6.25$,即 $b + 2 + \frac{1}{b} = 6.25$,整理得 $b + \frac{1}{b} = 4.25 = 4 + \frac{1}{4}$。显然基数 $b = 4$。
@@ -0,0 +1,146 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.1 进制转换</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### 题型一:位权与数码规则
1. ( )在七进制数中,不允许出现的数码是。
A. 0 B. 5 C. 6 D. 7
2. ( )下列写法中,不能作为五进制数的是。
A. (1423)5 B. (4032)5 C. (5104)5 D. (2240)5
3. ( )二进制数 $(101101)_2$ 对应的十进制数是。
A. 41 B. 45 C. 49 D. 53
4. ( )八进制数 $(347)_8$ 对应的十进制数是。
A. 223 B. 227 C. 231 D. 239
5. ( )十六进制数 $(2\text{AF})_{16}$ 对应的十进制数是。
A. 671 B. 687 C. 703 D. 719
---
### 题型二:整数进制转换
6. ( )十进制数 94 的二进制表示是。
A. $(1011010)_2$ B. $(1011110)_2$
C. $(1101110)_2$ D. $(1111010)_2$
7. ( )十进制数 156 的八进制表示是。
A. $(224)_8$ B. $(234)_8$ C. $(244)_8$ D. $(264)_8$
8. ( )十进制数 1000 的十六进制表示是。
A. $(3\text{D}8)_{16}$ B. $(3\text{E}8)_{16}$
C. $(3\text{F}8)_{16}$ D. $(4\text{E}8)_{16}$
9. 把二进制数 $(1100101)_2$ 转换成十进制数,结果为 \_\_\_\_\_\_\_\_。
10. ( )二进制数 $(100000)_2$ 转换成八进制数是。
A. $(20)_8$ B. $(40)_8$ C. $(100)_8$ D. $(400)_8$
11. ( )二进制数 $(111010111)_2$ 转换成十六进制数是。
A. $(1\text{C}7)_{16}$ B. $(1\text{D}7)_{16}$
C. $(3\text{A}7)_{16}$ D. $(\text{D}7)_{16}$
12. ( )十六进制数 $(7\text{B}4)_{16}$ 的二进制表示是。
A. $(0111\ 1011\ 0100)_2$ B. $(0111\ 1010\ 0100)_2$
C. $(1011\ 0117\ 0100)_2$ D. $(0111\ 1011\ 1000)_2$
---
### 题型三:小数进制转换
13. ( )二进制小数 $(101.101)_2$ 对应的十进制数是。
A. 5.125 B. 5.5 C. 5.625 D. 5.75
14. ( )八进制小数 $(17.4)_8$ 对应的十进制数是。
A. 15.25 B. 15.5 C. 15.625 D. 17.5
15. ( )十六进制小数 $(\text{A}.\text{C})_{16}$ 对应的十进制数是。
A. 10.5 B. 10.75 C. 10.8 D. 10.12
16. 十进制小数 0.625 转换成有限二进制小数为 \_\_\_\_\_\_\_\_。
17. ( )十进制数 13.375 的二进制表示是。
A. $(1101.011)_2$ B. $(1101.101)_2$
C. $(1011.011)_2$ D. $(1100.111)_2$
18. 四进制小数 $(0.3)_4$ 对应的十进制数为 \_\_\_\_\_\_\_\_。
---
### 题型四:二、八、十六进制快速互转
19. ( )二进制数 $(11010110)_2$ 转换成八进制数是。
A. $(316)_8$ B. $(326)_8$ C. $(336)_8$ D. $(346)_8$
20. ( )八进制数 $(572)_8$ 转换成二进制数是。
A. $(101111010)_2$ B. $(101110010)_2$
C. $(111101010)_2$ D. $(101111100)_2$
21. ( )十六进制数 $(9\text{E})_{16}$ 转换成八进制数是。
A. $(226)_8$ B. $(236)_8$ C. $(246)_8$ D. $(256)_8$
22. 省略无意义的前导零和末尾零后,$(3\text{F}.8)_{16}$ 的二进制表示为 \_\_\_\_\_\_\_\_。
23. ( )二进制数 $(101011.011)_2$ 转换成十六进制数是。
A. $(2\text{B}.3)_{16}$ B. $(2\text{B}.6)_{16}$
C. $(5\text{B}.3)_{16}$ D. $(5\text{B}.6)_{16}$
24. 八进制数 $(745)_8$ 转换成十六进制数为 \_\_\_\_\_\_\_\_。
---
### 题型五:混合进制运算
25. ( )$(101101)_2 + (37)_8$ 的结果用十六进制表示为。
A. $(4\text{A})_{16}$ B. $(4\text{B})_{16}$ C. $(4\text{C})_{16}$ D. $(4\text{D})_{16}$
26. ( )$(2\text{A})_{16} - (1011)_2$ 的结果用八进制表示为。
A. $(35)_8$ B. $(36)_8$ C. $(37)_8$ D. $(40)_8$
27. ( )$(123)_4 \times (11)_2$ 的结果用四进制表示为。
A. $(1001)_4$ B. $(1101)_4$ C. $(1110)_4$ D. $(1201)_4$
28. $(1111)_2 + (17)_8 + (\text{F})_{16}$ 的十进制结果为 \_\_\_\_\_\_\_\_。
29. ( )二进制算式 $(10000)_2 \div (10)_2$ 的结果是。
A. $(100)_2$ B. $(1000)_2$ C. $(10000)_2$ D. $(1111)_2$
30. ( )$(3\text{E}8)_{16} + (1750)_8$ 的结果用十六进制表示为。
A. $(7\text{C}0)_{16}$ B. $(7\text{D}0)_{16}$
C. $(7\text{E}0)_{16}$ D. $(800)_{16}$
---
### 题型六:未知进制、位数与表示范围
31. ( )若 $(121)_b = (16)_{10}$,则基数 $b$ 为。
A. 2 B. 3 C. 4 D. 5
32. ( )若 $(23)_b = (17)_{10}$,则基数 $b$ 为。
A. 5 B. 6 C. 7 D. 8
33. 若 $(110)_b = (30)_{10}$,则 $b =$ \_\_\_\_\_\_\_\_。
34. ( )在同一基数 $b$ 下,若 $(24)_b + (13)_b = (42)_b$,则 $b$ 等于。
A. 5 B. 6 C. 7 D. 8
35. 若 $(100)_b = (10000)_2$,则基数 $b =$ \_\_\_\_\_\_\_\_。
36. ( )若 $(x2)_5 = (17)_{10}$,其中 $x$ 是一位五进制数码,则 $x$ 等于。
A. 2 B. 3 C. 4 D. 不存在
37. ( )表示十进制数 1023,至少需要多少位二进制数码?
A. 9 B. 10 C. 11 D. 12
38. ( )六位三进制无符号整数能够表示的最大十进制数是。
A. 242 B. 364 C. 728 D. 729
39. ( )用不超过四位的十六进制数表示正整数,一共可以表示多少个不同的正整数?
A. 65534 B. 65535 C. 65536 D. 65537
40. 若 $(12.1)_b = (6.25)_{10}$,则基数 $b =$ \_\_\_\_\_\_\_\_。
@@ -0,0 +1,79 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.10 OI 常识 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | D | A | B | C | D | A | B |
| **题号** | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| **答案** | NOI | D | A | B | C | D | A | `g++` | C | D |
| **题号** | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| **答案** | A | B | C | A | B | D | B |
---
### 详细解析
#### **题型一: 竞赛体系与评测术语**
1. **答案:A**
CSP-J 中的 `J` 是 **Junior**(初级)的缩写。
2. **答案:B**
CSP-S 中的 `S` 是 **Senior**(高级)的缩写。
3. **答案:C**
**AC** 是 **Accepted** 的缩写,表示你的程序通过了该测试点的所有测试用例,答案完全正确。
4. **答案:D**
**WA** 是 **Wrong Answer** 的缩写,表示你的程序在某个测试用例上输出了与标准答案不符的结果。
5. **答案:A**
**TLE** 是 **Time Limit Exceeded** 的缩写,表示你的程序运行时间超过了题目规定的时间限制。
6. **答案:B**
**MLE** 是 **Memory Limit Exceeded** 的缩写,表示你的程序在运行过程中占用的内存超过了题目规定的内存限制。
7. **答案:C**
**RE** 是 **Runtime Error** 的缩写,表示你的程序在运行时发生了错误,例如数组越界、除以零、非法内存访问等,导致程序异常终止。
8. **答案:D**
**CE** 是 **Compile Error** 的缩写,表示你的源代码存在语法错误,无法被编译器成功编译成可执行文件。
9. **答案:A**
OI 赛制(如 CSP-J/S、NOIP)通常采用按测试点或子任务计分的方式。选手每通过一个测试点或完成一个子任务的所有测试点,就能获得相应的分数,最终总分为各部分得分之和。
10. **答案:B**
ACM/ICPC 赛制(国际大学生程序设计竞赛)的排名规则是:首先比较**通过的题目总数**,通过题目数越多的队伍排名越靠前。在通过题目数相同的情况下,再比较**罚时**(Penalty Time),罚时越少的队伍排名越靠前。
11. **答案:NOI**
“全国青少年信息学奥林匹克竞赛”的英文全称是 **N**ational **O**lympiad in **I**nformatics,其缩写为 **NOI**。
12. **答案:D**
CSP-J/S 第一轮(初赛)是笔试,主要考查选手对计算机科学基础知识、算法原理、数据结构以及程序代码阅读理解的能力。
#### **题型二: 编译、命令与竞赛环境**
13. **答案:A**
在 Linux 或类 Unix 环境下,使用 `g++` 编译器编译 C++ 程序的标准命令格式是:`g++ <源文件名> -o <输出可执行文件名>`。
14. **答案:B**
`ls` (list) 命令用于列出当前目录下的文件和子目录。
15. **答案:C**
`pwd` (print working directory) 命令用于显示用户当前所在的工作目录的完整路径。
16. **答案:D**
`cd` (change directory) 命令用于切换当前工作目录。
17. **答案:A**
C++ 语言的源文件通常使用 `.cpp`、`.cc` 或 `.cxx` 作为扩展名,其中 `.cpp` 最为常见。
18. **答案:`g++`**
GNU Compiler Collection (GCC) 中用于编译 C++ 语言的编译器命令通常是 `g++`。
19. **答案:C**
断点是调试过程中的一个重要工具。在代码的某一行设置断点后,当程序执行到该行时会自动暂停,允许开发者检查此时的变量值、调用栈等程序状态,以便定位问题。
20. **答案:D**
“对拍”是一种在竞赛中常用的程序正确性验证方法。它通过编写一个简单但确保正确的暴力算法程序,和一个待测试的、可能更高效的程序,在大量自动生成的随机数据上运行这两个程序,并比较它们的输出结果是否一致。如果不一致,就说明待测程序存在 bug。
#### **题型三: 人物、奖项与学科历史**
21. **答案:A**
图灵奖(A.M. Turing Award)由美国计算机协会(ACM)设立,是公认的计算机科学领域的最高荣誉,常被称为“计算机界的诺贝尔奖”。
22. **答案:B**
本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)于 20 世纪 80 年代初在贝尔实验室领导开发了 C++ 语言,它是在 C 语言的基础上扩展而来的。
23. **答案:C**
克劳德·香农(Claude Shannon)在 1948 年发表了划时代的论文《通信的数学理论》,为信息论和数字通信奠定了坚实的数学基础。
24. **答案:A**
冯·诺依曼体系结构的核心思想是“存储程序控制”,即计算机的指令(程序)和数据都以二进制形式统一存放在存储器中,并可以被 CPU 访问和处理。
25. **答案:B**
林纳斯·托瓦兹(Linus Torvalds)在 1991 年创建了 Linux 操作系统的内核,并将其开源,极大地推动了开源软件和操作系统的发展。
26. **答案:D**
蒂姆·伯纳斯-李(Tim Berners-Lee)在 1989 年发明了万维网(WWW),并开发了世界上第一个网页浏览器和服务器,为互联网的普及奠定了基础。
27. **答案:B**
**IOI** 是 **I**nternational **O**lympiad in **I**nformatics 的缩写,即国际信息学奥林匹克竞赛,是面向全球中最高水平的青少年信息学竞赛。
@@ -0,0 +1,118 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.10 OI 常识</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 竞赛体系与评测术语**
1. ( )CSP-J 中字母 J 表示?
A. Junior B. Judge
C. Java D. Joint
2. ( )CSP-S 中字母 S 表示?
A. Source B. Senior
C. System D. Standard
3. ( )在线评测中,AC 通常表示?
A. Array Crash B. Automatic Check
C. Accepted D. Answer Compile
4. ( )在线评测中,WA 通常表示?
A. Write Again B. Waiting Answer
C. Wrong Array D. Wrong Answer
5. ( )在线评测中,TLE 通常表示?
A. Time Limit Exceeded B. Total Logic Error
C. Test Lost Entry D. Type Limit Error
6. ( )在线评测中,MLE 通常表示?
A. Memory Link Error
B. Memory Limit Exceeded
C. Main Logic Error
D. Machine Load Error
7. ( )在线评测中,RE 通常表示?
A. Result Equal B. Random Evaluation
C. Runtime Error D. Read End
8. ( )在线评测中,CE 通常表示?
A. Correct Execution B. Code End
C. Check Error D. Compile Error
9. ( )OI 赛制下,一道题常见的计分方式是?
A. 按通过的测试点或子任务获得部分分 B. 只有全对才得分
C. 按提交次数加分 D. 按代码长度计分
10. ( )ACM/ICPC 风格竞赛中,排名通常优先比较?
A. 最后一次提交时间 B. 通过题目数,再比较罚时
C. 代码总行数 D. 内存总和
11. “全国青少年信息学奥林匹克竞赛”的英文缩写是 \_\_\_\_\_\_\_\_\_\_\_\_。
12. ( )CSP-J/S 第一轮主要考查?
A. 大型项目开发
B. 硬件焊接
C. 纯英语写作
D. 通用和实用的计算机科学知识及程序理解
---
### **题型二: 编译、命令与竞赛环境**
13. ( )把 `main.cpp` 编译为名为 `main` 的可执行文件,常用命令是?
A. `g++ main.cpp -o main` B. `g++ main -o main.cpp`
C. `run main.cpp` D. `compile main`
14. ( )Linux 终端中列出当前目录文件常用命令是?
A. `mkdir` B. `ls` C. `cd` D. `pwd`
15. ( )Linux 终端中显示当前工作目录路径的命令是?
A. `cd` B. `cp` C. `pwd` D. `ls`
16. ( )Linux 终端中切换工作目录的命令是?
A. `ls` B. `pwd` C. `rm` D. `cd`
17. ( )C++ 源文件常见扩展名是?
A. `.cpp` B. `.exe` C. `.pdf` D. `.jpg`
18. GNU C++ 编译器命令通常写作 \_\_\_\_\_\_\_\_\_\_\_\_。
19. ( )调试程序时设置断点的主要作用是?
A. 自动证明程序正确
B. 提高程序运行速度
C. 让程序运行到指定位置暂停以检查状态
D. 永久删除该行代码
20. ( )“对拍”通常指?
A. 两人同时敲键盘
B. 只运行样例
C. 比较两份代码长度
D. 用暴力程序与待测程序在大量随机数据上比较输出
---
### **题型三: 人物、奖项与学科历史**
21. ( )计算机科学领域著名的最高奖项是?
A. 图灵奖 B. 诺贝尔数学奖
C. 普利策奖 D. 奥斯卡奖
22. ( )C++ 语言的设计者是?
A. Claude Shannon B. Bjarne Stroustrup
C. Alan Turing D. Edsger Dijkstra
23. ( )1948 年发表《通信的数学理论》、奠定信息论基础的是?
A. Donald Knuth B. Linus Torvalds
C. Claude Shannon D. John von Neumann
25. ( )冯·诺依曼体系结构的核心特征之一是?
A. 程序和数据共同存放在存储器中 B. 只能使用十进制
C. 没有输入输出设备 D. 程序必须写在纸带上且不能修改
26. ( )Linux 内核最初由谁创建?
A. Tim Berners-Lee B. Linus Torvalds
C. Bjarne Stroustrup D. Claude Shannon
28. ( )万维网(World Wide Web)的发明者是?
A. Alan Turing B. Dennis Ritchie
C. John McCarthy D. Tim Berners-Lee
30. ( )IOI 的中文通常是?
A. 国际机器人足球赛 B. 国际信息学奥林匹克竞赛
C. 国际数学奥林匹克竞赛 D. 国际物理奥林匹克竞赛
@@ -0,0 +1,213 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.11 计算机基础知识 答案</b></font></center>
<center><font size="5"><b>答案与解析</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | D | A | B | C | D | A | B |
| 题号 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | C | D | 1024 | B | C | D | A | 2048 | C | D |
| 题号 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | D | A | 4000 | C | D | A | 8589934592 |
| 题号 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | C | D | A | B | C | D | A | B | C | D |
| 题号 | 41 | 42 | 43 | 44 | 45 |
| :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | 路径 | D | A |
| 题号 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
| :------: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| **答案** | B | C | D | A | B | C | D | A | B | C |
| **题号** | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
| **答案** | D | A | B | C | D | A | B | C | D | A |
| 题号 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
| :------: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| **答案** | B | C | D | A | B | C | D | A | 主键 | C |
| 题号 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
| :------: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| **答案** | D | A | B | C | D | A | B | C | 7 | A |
| 题号 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
| :------: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :------: | :--: |
| **答案** | B | C | D | A | B | C | D | A | $O(n^2)$ | C |
| **题号** | 96 | 97 | 98 | 99 | 100 | | | | | |
| **答案** | D | A | B | C | D | | | | | |
### 详细解析
#### 题型一:计算机组成与硬件
1. **答案:A**
CPU(中央处理器)是计算机的大脑,其内部包含运算器和控制器,负责执行程序指令和进行各种算术与逻辑运算。
2. **答案:B**
RAM(Random-Access Memory,随机存取存储器),即我们常说的内存条,是一种易失性存储器,断电后其中存储的数据会全部丢失。
3. **答案:C**
寄存器(Register)是位于 CPU 内部的存储单元,它的速度是所有存储部件中最快的,但容量非常小,主要用于临时存放指令、数据和地址。
4. **答案:D**
高速缓存(Cache)是位于 CPU 和主存之间的一层高速存储器。它利用程序的局部性原理,缓存 CPU 近期可能需要的数据,从而有效缓解 CPU 与主存之间巨大的速度差异。
5. **答案:A**
输入设备用于向计算机输入信息,例如键盘、鼠标、扫描仪、麦克风等。
6. **答案:B**
输出设备用于将计算机处理的结果呈现给用户,例如显示器、打印机、扬声器等。
7. **答案:C**
总线(Bus)是计算机各部件之间传输信息的公共通道,根据传输内容的不同,分为数据总线、地址总线和控制总线。
8. **答案:D**
固态硬盘(SSD)使用闪存芯片存储数据,没有机械硬盘(HDD)的旋转盘片和移动磁头,因此没有寻道时间,随机访问速度远快于机械硬盘,且抗震性更好。
9. **答案:A**
一个有 $n$ 位地址总线的处理器,可以产生 $2^n$ 个不同的地址。如果按字节编址,每个地址对应一个字节,那么它理论上最多可以寻址 $2^n$ 个字节。对于 32 位地址总线,即可寻址 $2^{32}$ 字节(即 4GB)。
10. **答案:B**
按字节编址(Byte-addressable)是现代计算机最普遍的内存组织方式,它意味着内存被划分为以字节为单位的连续单元,每一个字节都有一个唯一的地址。
11. **答案:C**
`Hz` 是频率单位,表示“次/秒”。`G`(Giga)是数量前缀,表示 $10^9$。因此,3 GHz 约等于 $3 \times 10^9$ 次每秒。
12. **答案:D**
计算机启动时,固化在主板芯片上的固件(如 BIOS 或 UEFI)会首先运行,进行开机自检(POST),完成硬件的初始化,然后按照预设顺序寻找并加载可启动设备(如硬盘、U盘)上的操作系统。
13. **答案:1024**
地址从 0 到 1023,共包含 $1023 - 0 + 1 = 1024$ 个不同的地址。按字节编址,每个地址对应 1 字节,所以总容量为 1024 字节(即 1KB)。
14. **答案:B**
多核处理器将多个独立的计算核心(Core)集成在一块芯片上。每个核心都拥有自己的一套执行单元(如 ALU、寄存器),可以独立地执行指令流(线程)。
15. **答案:C**
DMA(Direct Memory Access,直接内存访问)是一种允许外设(如硬盘、网卡)与主存之间直接传输数据,而无需 CPU 持续干预的机制。这极大地减轻了 CPU 的负担,提高了系统效率。
#### 题型二:容量单位与存储计算
16. **答案:D**
1 字节(Byte)由 8 个二进制位(bit)组成。
17. **答案:A**
在计算机科学中,容量单位通常按 $2^{10}=1024$ 换算。$1 \text{MB} = 1024 \text{KB} = 1024 \times 1024 \text{B} = 1048576 \text{Bytes}$。
18. **答案:2048**
$2 \text{MB} = 2 \times 1024 \text{KB} = 2048 \text{KB}$。
19. **答案:C**
总像素数 = $1024 \times 768$。
总位数 = $1024 \times 768 \times 24$ bits。
总字节数 = $(1024 \times 768 \times 24) \div 8 = 2,359,296$ Bytes。
转换为 MB = $2,359,296 \div 1024 \div 1024 = 2.25$ MB。
20. **答案:D**
总字节数 = $(800 \times 600 \times 32) \div 8 = 1,920,000$ Bytes。
转换为 MB = $1,920,000 \div 1024 \div 1024 \approx 1.831$ MB。
21. **答案:A**
总字节数 = $(2048 \times 1024 \times 32) \div 8 = 8,388,608$ Bytes。
$8,388,608 \div 1024 \div 1024 = 8$ MB。
22. **答案:B**
总字节数 = $44100 \times (16 \div 8) \times 2 \times 60 = 10,584,000$ Bytes。
转换为 MB = $10,584,000 \div 1024 \div 1024 \approx 10.09$ MB。
23. **答案:C**
总字节数 = $48000 \times (16 \div 8) \times 1 \times 30 = 2,880,000$ Bytes。
转换为 MB = $2,880,000 \div 1024 \div 1024 \approx 2.75$ MB。
24. **答案:D**
- 单帧大小 = $1920 \times 1080 \times (24 \div 8) = 6,220,800$ Bytes $\approx 5.93$ MiB。
- 10 秒视频总大小 = $5.93 \times 25 \times 10 \approx 1482.5$ MiB $\approx 1.45$ GiB。
数量级最接近 1.45GB。
25. **答案:A**
一个标准 ASCII 字符占用 1 个字节。因此,5000 个 ASCII 字符大约占用 5000 字节(约 5KB)。
26. **答案:4000**
一个 32 位整数占用 $32 \div 8 = 4$ 个字节。1000 个元素共占用 $1000 \times 4 = 4000$ 字节。
27. **答案:C**
网络速率单位中的 `b` 指的是 bit。100 Mbps = 100 Megabits per second。要将其转换为 MB (MegaBytes),需要除以 8。$100 \div 8 = 12.5$ MB/s。
28. **答案:D**
$1 \text{GiB} = 1024 \text{MiB}$。所需时间 = 总大小 / 速率 = $1024 \div 20 = 51.2$ 秒。
29. **答案:A**
压缩后的大小 = 原大小 $\times$ 压缩率 = $200 \text{MB} \times 35\% = 200 \times 0.35 = 70 \text{MB}$。
30. **答案:8589934592**
$8 \text{GiB} = 8 \times 1024 \text{MiB} = 8 \times 1024 \times 1024 \text{KiB} = 8 \times 1024^3 \text{Bytes} = 8,589,934,592$ Bytes。
31. **答案:C**
操作系统的核心职能是作为硬件和用户(或应用程序)之间的接口,负责管理计算机的所有硬件和软件资源,并为上层程序提供统一、便捷的服务。
32. **答案:D**
`Linux` 是一个著名的开源操作系统内核,常见的发行版如 Ubuntu, CentOS 都基于此内核。`HTML` 是标记语言,`JPEG` 是图像格式,`MySQL` 是数据库系统。
33. **答案:A**
进程是操作系统进行资源分配和调度的基本单位,可以看作是一个正在执行中的程序及其相关资源(内存、文件句柄等)的总和。
34. **答案:B**
线程是进程内部的一个执行单元,是 CPU 调度的最小单位。一个进程可以包含多个线程,它们共享该进程的资源。
35. **答案:C**
文件扩展名 `.txt` 是纯文本文件(Plain Text)的通用标识。
36. **答案:D**
目录(或称文件夹)是文件系统中用于组织和管理文件的一种结构,它可以包含文件和其他子目录。
37. **答案:A**
绝对路径提供了从文件系统的根目录(如 Linux 的 `/`)或驱动器盘符(如 Windows 的 `C:\`)开始的完整、唯一的路径,其含义不随当前工作目录的改变而改变。
38. **答案:B**
虚拟内存机制为每个进程提供了一个独立的、连续的、巨大的虚拟地址空间。它使得程序可以不必关心物理内存的实际大小和碎片情况,并支持内存的按需分页、交换等高级管理功能。
39. **答案:C**
在虚拟内存管理中,当 CPU 需要访问一个不在物理内存中的页面时,会产生缺页中断。操作系统需要从磁盘加载该页面到物理内存。如果此时物理内存已满,就必须选择一个已有的页面换出(写回磁盘),这个过程称为页面置换。
40. **答案:D**
“只读”(Read-only)权限意味着用户可以查看文件的内容,但不能对其进行修改、保存或删除。
41. **答案:A**
开源软件的核心特征是其源代码是公开的,使用者可以根据相应的开源许可证(如 GPL, MIT)自由地查看、修改、分发代码。
42. **答案:B**
编译型语言(如 C++, Go)的执行过程是:先由编译器将全部源代码一次性地翻译成计算机可直接执行的目标代码(机器码),然后才能运行这个生成的文件。
43. **答案:路径**
程序在运行时报告“找不到文件”(File Not Found)错误,最常见的原因是文件名拼写错误,或者程序执行时所在的工作目录与文件实际存放的目录不符(即路径错误)。
44. **答案:D**
当多个进程或线程并发地访问和修改同一块共享数据,且没有使用锁等同步机制来保护时,最终结果会因为执行顺序的细微差异而变得不可预测,这种情况被称为竞态条件(Race Condition)。
45. **答案:A**
死锁的四个必要条件是:互斥使用、占有并等待、非抢占、循环等待。选项 A 描述的资源可被无限复制,意味着资源充足,不会产生争抢,恰恰是避免死锁的一个理想情况,而不是导致死锁的条件。
46. **答案:B**。`IP` 地址(网际协议地址)是网络层概念,用于在复杂的网络互联中唯一标识设备接口,并实现跨网络的数据包路由与寻址。
47. **答案:C**。`DNS`(域名系统)相当于互联网的电话簿,主要负责将易于人类记忆的域名(如 `www.luogu.com.cn`)解析转换为机器可读的 `IP` 地址。
48. **答案:D**。`HTTP`(超文本传输协议)是应用层协议,主要用于 Web 浏览器(客户端)和 Web 服务器之间传输 HTML 页面、图片等资源。
49. **答案:A**。`HTTPS` 在 `HTTP` 的基础上叠加了 `SSL/TLS` 协议,提供了加密传输、身份认证和数据完整性保护,保证了通信安全。
50. **答案:B**。`TCP` 是一种面向连接的、可靠的传输层协议,它通过三次握手、确认重传、拥塞控制等机制确保字节流有序、无误地送达。
51. **答案:C**。`UDP` 是一种无连接的传输层协议,它不保证数据包的顺序和送达,但因为没有建立连接和重传的开销,传输速度快,常用于视频直播、在线游戏等对实时性要求高的场景。
52. **答案:D**。路由器工作在网络层,其主要功能是根据 `IP` 地址,在不同的网络(如局域网与广域网之间)中为数据包选择最佳路径并进行转发。
53. **答案:A**。交换机工作在数据链路层,主要用于局域网内部。它通过记录设备的 `MAC` 地址表,直接将数据帧转发到目标端口。
54. **答案:B**。`IPv4` 地址由 32 个二进制位组成(通常表示为 4 个十进制数,用点隔开)。
55. **答案:C**。`IPv6` 地址由 128 个二进制位组成,解决了 `IPv4` 地址枯竭的问题。
56. **答案:D**。`MAC` 地址(物理地址)通常固化在网卡硬件中,长度为 48 位,用于在局域网的链路层中唯一标识一个网络接口。
57. **答案:A**。`IP` 地址负责找到目标主机,而端口号(Port)负责区分该主机上运行的众多不同网络应用程序或服务(如 80 端口通常对应 Web 服务)。
58. **答案:B**。网络时延由排队时延、处理时延、传输时延(发送数据包耗时)和传播时延(信号在物理介质中飞行耗时)组成。源代码编译属于本地处理,与网络传输无关。
59. **答案:C**。网络带宽(Bandwidth)通常指网络链路在单位时间内能够传输的最大数据量(数据吞吐率上限),单位常用 bps(比特每秒)。
60. **答案:D**。丢包指网络中传输的数据包由于网络拥塞、路由器缓冲区满、线路干扰等原因未能成功到达目的地的现象。
61. **答案:A**。局域网(`LAN`, Local Area Network)通常指覆盖范围较小(如一个家庭、一所学校或一栋办公楼)的计算机网络。
62. **答案:B**。浏览器获取网址后,必须先通过向 `DNS` 服务器发起查询,获取目标域名的 `IP` 地址,然后才能建立连接。
63. **答案:C**。子网掩码与 `IP` 地址结合使用,用于告诉路由器和主机,一个 `IP` 地址中哪部分代表网络地址(Network ID),哪部分代表主机地址(Host ID)。
64. **答案:D**。`404 Not Found` 是经典的 `HTTP` 状态码,表示客户端请求的资源(网页、图片等)在服务器上不存在。
65. **答案:A**。`HTTP` 状态码 `200 OK` 表示客户端的请求已被服务器成功接收、理解并处理。
66. **答案:B**。关系型数据库(如 MySQL、SQL Server)将数据组织成二维表格的形式,表由行(记录)和列(字段/属性)组成。
67. **答案:C**。主键(Primary Key)是表中一列或多列的组合,其值能唯一且无歧义地标识表中的每一行记录。
68. **答案:D**。`SQL` 语言中,`SELECT` 用于从数据库中查询/提取数据。`DELETE` 用于删除,`UPDATE` 用于更新,`DROP` 用于删除表或库。
69. **答案:A**。`WHERE` 子句用于在 `SELECT`、`UPDATE`、`DELETE` 语句中设定筛选条件,仅处理满足条件的行。
70. **答案:B**。数据库索引类似于书籍的目录,它通过额外的数据结构(如 B+ 树)来极大地加快在特定列上进行条件查找的速度。
71. **答案:C**。外键(Foreign Key)用于在两张表之间建立连接,它指向另一张表的主键,从而保证数据的一致性和参照完整性。
72. **答案:D**。事务的原子性(Atomicity)要求事务中的所有操作被视为一个不可分割的工作单元,要么全部执行成功并提交,要么在遇到错误时全部回滚(撤销),不能只执行一部分。
73. **答案:A**。数据库备份的主要目的是防止数据丢失。当发生硬件故障、黑客攻击或人为误删除时,可以通过备份恢复数据。
74. **答案:主键**。学号在学生表中具有唯一性,不会重复,最适合作为主键(Primary Key)。
75. **答案:C**。`SELECT name` 意为提取姓名列,`FROM student` 意为从学生表提取,`WHERE score >= 90` 为筛选条件。组合起来即查询成绩 $\ge 90$ 的学生姓名。
76. **答案:D**。`ASCII`(美国信息交换标准代码)是最基础的字符编码,主要涵盖英文字母、数字、标点符号及一些控制字符。
77. **答案:A**。`Unicode`(万国码)致力于为世界上所有的字符、符号提供一个统一且唯一的编码标准,解决跨语言、跨平台的乱码问题。
78. **答案:B**。`UTF-8` 是一种针对 `Unicode` 的可变长度字符编码(使用 1~4 个字节)。它最大的优点是向后兼容 `ASCII` 编码(英文占 1 字节)。
79. **答案:C**。`JPEG` 是一种支持有损压缩的图像格式,由于其极高的压缩率且肉眼难以察觉细节损失,非常适合保存色彩丰富的自然风景照片。
80. **答案:D**。`PNG` 采用无损压缩算法,保留了图像的所有细节,并且支持 Alpha 透明通道,常用于网页设计、图标和需要透明背景的图像。
81. **答案:A**。分辨率 $1920 \times 1080$ 指的是图像的尺寸:水平方向包含 1920 个像素,垂直方向包含 1080 个像素。
82. **答案:B**。颜色深度为 24 位意味着每个像素用 24 个二进制位(通常是 RGB 各 8 位)来记录颜色,总共可以表示 $2^{24}$(约 1677 万)种颜色,即“真彩色”。
83. **答案:C**。采样率是指每秒钟对音频信号采样的次数。采样率越高,记录的声音波形越细腻,高频细节越丰富,但同时每秒产生的数据量也成正比增大。
84. **答案:7**。标准 `ASCII` 码使用 7 个二进制位进行编码,最高位通常补 0,凑成 1 字节(8 位)。共可表示 $2^7=128$ 个字符。
85. **答案:A**。无损压缩(如 ZIP 压缩文件、FLAC 音频、PNG 图像)利用数据的统计冗余进行压缩,解压后得到的数据与压缩前的原始数据完全一致,没有任何信息丢失。
86. **答案:B**。编译器(Compiler)负责将人类编写的高级语言源代码(如 C++)整体扫描,并将其翻译成计算机可直接执行的目标代码(机器码)。
87. **答案:C**。链接器(Linker)的作用是在编译完成后,将编译器生成的多个目标文件以及调用的外部静态/动态库组合在一起,解决符号引用问题,最终生成可执行文件。
88. **答案:D**。拼写错误、少写分号、括号不匹配等违背语言语法的错误,在编译阶段就会被编译器捕捉并报出编译错误(CE)。
89. **答案:A**。运行时错误(RE)是在程序实际执行过程中触发的异常,例如数组越界访问、除数为零、非法内存访问等。
90. **答案:B**。时间复杂度通常使用大 O 渐进表示法,用来描述随着输入数据规模 $n$ 的增长,算法执行的基本操作次数的增长趋势。
91. **答案:C**。空间复杂度描述的是随着输入数据规模 $n$ 的增长,算法在运行过程中所需要占用的额外内存空间的增长趋势。
92. **答案:D**。解释型语言(如 Python, JavaScript)不需要预先编译成机器码,而是由解释器在程序运行时,逐行读取源代码并实时翻译执行。
93. **答案:A**。单元测试(Unit Testing)是软件开发中的一种测试方法,专门用于验证程序中最小的可测试单元(如一个函数或一个类的方法)在给定输入下是否能产生预期的输出。
94. **答案:$O(n^2)$**。在大 O 渐进表示法中,只保留影响增长趋势的最高阶项,并忽略其常数系数。对于 $3n^2 + 5n + 7$,最高阶是 $n^2$。
95. **答案:C**。代码能够成功编译说明没有语法错误;能够运行说明没有致命的运行时错误。但对特定输入给出了错误的输出,这属于代码内部算法或逻辑思路设计的错误(即逻辑错误/WA)。
96. **答案:D**。强密码应具备足够的长度,包含大小写字母、数字及特殊符号,并坚决避免使用生日、姓名、电话等容易被社工猜测的个人信息。
97. **答案:A**。双因素认证(2FA)除了要求输入密码(你知道的)外,还要求提供第二种凭证(如手机验证码、指纹,即“你拥有的”或“你本身的”),极大提升了账户安全性。
98. **答案:B**。这是一种典型的“网络钓鱼”攻击手法,攻击者通过伪装成官方(如银行、系统管理员)发送邮件,诱导受害者在伪造的网页上输入账号密码。
99. **答案:C**。软件厂商推送安全更新(打补丁)的主要目的,是为了修复已被发现的代码漏洞,防止黑客利用这些漏洞对用户的系统进行攻击或提权。
100. **答案:D**。定期将重要数据进行离线备份(如存入移动硬盘)或异地备份(如存入云端),是应对硬盘等物理硬件损坏、人为误删除以及防范勒索软件(加密文件勒索赎金)最有效的数据保全手段。
@@ -0,0 +1,472 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.11 计算机基础知识</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 计算机组成与硬件**
1. ( )计算机中负责执行指令和进行算术逻辑运算的核心部件是?
A. `CPU` B. 内存条
C. 显示器 D. 硬盘
2. ( )断电后通常会丢失其中数据的存储器是?
A. 光盘 B. `RAM`
C. `SSD` D. 机械硬盘
3. ( )`CPU` 中速度最快、容量很小、直接保存当前操作数的存储部件是?
A. U 盘 B. 光盘
C. 寄存器 D. 机械硬盘
4. ( )高速缓存 `Cache` 的主要作用是?
A. 永久保存用户文件 B. 代替所有外部存储
C. 提供网络地址 D. 缓解 `CPU` 与主存速度差异
5. ( )下列设备中属于输入设备的是?
A. 键盘 B. 显示器
C. 打印机 D. 扬声器
6. ( )下列设备中属于输出设备的是?
A. 麦克风 B. 打印机
C. 鼠标 D. 扫描仪
7. ( )主板上的总线主要用于?
A. 只执行加法
B. 生成网页域名
C. 在各部件之间传输数据、地址和控制信号
D. 只存储图片
8. ( )固态硬盘 `SSD` 相较机械硬盘 `HDD` 的典型特点是?
A. 必须联网才能使用
B. 断电即丢失数据
C. 容量单位只能是 bit
D. 没有机械寻道部件,随机访问通常更快
9. ( )一个处理器有 32 位地址总线,按字节编址,理论上最多可直接寻址()字节?
A. $2^{32}$ B. 32
C. $2^{16}$ D. $2^{64}$
10. ( )“按字节编址”意味着?
A. 地址只能是十进制
B. 每个存储地址对应一个字节
C. 每个地址对应一个二进制位
D. 每个地址对应一整块硬盘
11. ( )`CPU` 主频为 3 GHz,表示时钟频率约为?
A. $3 \times 10^3$ 次每秒 B. 3 次每秒
C. $3 \times 10^9$ 次每秒 D. $3 \times 10^6$ 次每秒
12. ( )计算机启动时,固件通常首先完成的工作包括?
A. 编译所有用户程序 B. 删除内存中的所有文件
C. 建立互联网域名 D. 硬件初始化并寻找可启动设备
13. 若地址从 0 到 1023,按字节编址,则可表示的存储容量为 ________ 字节。
14. ( )多核处理器中的“核”通常指?
A. 网络端口 B. 可独立执行指令流的处理核心
C. 硬盘分区 D. 文件夹数量
15. ( )`DMA` 的主要作用是?
A. 提高显示器分辨率
B. 为文件加密
C. 让外设与内存之间传输数据时减少 `CPU` 逐字节参与
D. 把十进制转换成二进制
---
### **题型二: 容量单位与存储计算**
16. ( )1 字节等于()个二进制位。
A. 4 B. 16 C. 1024 D. 8
17. ( )按 1KB = 1024B,1MB 等于()字节。
A. 1048576 B. 1000000 C. 1024 D. 8388608
18. 按二进制容量单位,2MB 等于 ________ KB。
19. ( )一幅未压缩图像分辨率为 $1024 \times 768$,每像素 24 位,所需存储空间约为?
A. 约 18.000MB B. 786432B
C. 约 2.250MB D. 约 0.281MB
20. ( )一幅未压缩图像分辨率为 $800 \times 600$,每像素 32 位,所需存储空间约为?
A. 约 0.229MB B. 约 14.648MB
C. 480000B D. 约 1.831MB
21. ( )一幅未压缩图像分辨率为 $2048 \times 1024$,每像素 32 位,所需存储空间约为?
A. 8MB B. 约 1.000MB
C. 约 64.000MB D. 2097152B
22. ( )未压缩音频采样率 44100Hz、量化位数 16 位、2 声道、时长 60 秒,大小约为?
A. 2646000B B. 10.09MB
C. 1.26MB D. 20.19MB
23. ( )未压缩音频采样率 48000Hz、量化位数 16 位、1 声道、时长 30 秒,大小约为?
A. 5.49MB B. 1440000B
C. 2.75MB D. 0.34MB
24. ( )一段 10 秒、每秒 25 帧、每帧 $1920 \times 1080$、每像素 24 位的未压缩视频,大小数量级最接近?
A. 145MB B. 14.5GB
C. 1.45MB D. 1.45GB
25. ( )一个文本文件含 5000 个 ASCII 字符,不考虑额外格式信息,大小约为?
A. 5000 字节 B. 5000 位
C. 40000 字节 D. 625 字节
26. 一个 32 位整数数组含 1000 个元素,数组数据区占 ________ 字节。
27. ( )网速 100Mbps 理论上每秒最多传输约()MB 数据。
A. 8 B. 800 C. 12.5 D. 100
28. ( )一个文件大小为 1GiB,以稳定 20MiB/s 传输,理论时间约为?
A. 20 秒 B. 80 秒
C. 1024 秒 D. 51.2 秒
29. ( )若压缩率定义为“压缩后大小/原大小”,原文件 200MB、压缩率 35%,压缩后约为?
A. 70MB B. 35MB
C. 130MB D. 235MB
30. 8GiB 内存共有 ________ 字节。
---
### **题型三: 操作系统、文件与软件**
31. ( )操作系统的主要职责是?
A. 只编译 C++
B. 只保存网页
C. 管理硬件与软件资源并为程序提供服务
D. 只编辑图片
32. ( )下列属于操作系统的是?
A. `HTML` B. `JPEG`
C. `MySQL` 查询语句 D. `Linux`
33. ( )进程是?
A. 正在执行的程序实例 B. 硬盘上的源代码文件
C. 一个网络域名 D. 一个字符编码
34. ( )线程通常被看作?
A. 网络协议 B. 进程内的执行单元
C. 独立硬盘分区 D. 文件扩展名
35. ( )文件扩展名 `.txt` 通常表示?
A. 压缩视频 B. 数据库服务器
C. 纯文本文件 D. 可执行文件
36. ( )目录(文件夹)的主要作用是?
A. 执行算术指令 B. 分配 `IP` 地址
C. 压缩图像像素 D. 组织文件和子目录
37. ( )绝对路径的特点是?
A. 从文件系统根或盘符开始描述完整位置
B. 必须只含一个文件名
C. 随当前目录改变含义
D. 只能用于网络文件
38. ( )虚拟内存的主要作用之一是?
A. 替代网络协议
B. 为进程提供统一的虚拟地址空间并支持内存管理
C. 让 `CPU` 主频翻倍
D. 永久保存所有寄存器
39. ( )页面置换发生在?
A. 键盘输入字符时
B. 显示器刷新时
C. 需要装入新页面而可用物理页不足时
D. 编译器检查语法时
40. ( )文件权限中的“只读”通常意味着?
A. 文件不能被查看 B. 文件自动删除
C. 只能通过网络打开 D. 允许读取但不允许修改内容
41. ( )开源软件通常意味着?
A. 源代码按相应许可证向使用者开放 B. 软件一定免费且无许可证
C. 任何人可删除作者署名 D. 只能在 Linux 上运行
42. ( )编译型语言的一般过程是?
A. 只能在浏览器中执行 B. 先把源代码翻译成目标代码,再执行
C. 每次只解释一个像素 D. 无需任何翻译
43. 程序运行时出现“找不到文件”,首先应检查文件名以及 ________ 是否正确。
44. ( )多个进程同时修改同一共享数据而没有同步,可能产生?
A. 图像压缩 B. 地址翻译
C. 域名解析 D. 竞态条件
45. ( )死锁通常需要多个条件同时成立,其中不包括?
A. 所有资源都可被无限复制 B. 互斥使用
C. 占有并等待 D. 循环等待
---
### **题型四: 计算机网络与互联网**
46. ( )`IP` 地址的主要作用是?
A. 保存字符颜色 B. 标识网络中的接口并支持路由转发
C. 表示文件大小 D. 编译源代码
47. ( )域名系统 `DNS` 的主要作用是?
A. 检测语法错误 B. 管理 `CPU` 寄存器
C. 把域名解析为 `IP` 地址等记录 D. 压缩视频
48. ( )`HTTP` 主要用于?
A. 硬盘分区
B. 编译 C++
C. 绘制电路图
D. Web 客户端与服务器传输资源和请求响应
49. ( )`HTTPS` 相较 `HTTP` 主要增加了?
A. 基于 `TLS` 的加密、认证与完整性保护
B. 更大的显示器分辨率
C. 本地文件压缩
D. `CPU` 超频
50. ( )`TCP` 的典型特点是?
A. 只能在局域网使用
B. 面向连接、可靠、有序的字节流传输
C. 无连接且不保证到达
D. 只用于图片格式
51. ( )`UDP` 的典型特点是?
A. 自动保证顺序和重传
B. 只能传输文本
C. 无连接、开销较小但不保证可靠到达
D. 必须先建立三次握手
52. ( )路由器的主要作用是?
A. 把键盘输入显示到屏幕 B. 只存储网页
C. 执行数据库排序 D. 在不同网络之间转发数据包
53. ( )交换机在局域网中的典型作用是?
A. 根据链路层地址转发帧 B. 把域名翻译成 `IP`
C. 编译源程序 D. 产生随机数
54. ( )`IPv4` 地址长度为?
A. 128 位 B. 32 位
C. 16 位 D. 64 位
55. ( )`IPv6` 地址长度为?
A. 64 位 B. 256 位
C. 128 位 D. 32 位
56. ( )`MAC` 地址通常用于?
A. 表示网页标题
B. 存储程序返回值
C. 描述数据库主键类型
D. 局域网链路层接口标识
57. ( )端口号的作用是?
A. 区分同一主机上的不同网络应用或服务
B. 区分硬盘扇区
C. 表示屏幕像素
D. 确定 `CPU` 位数
58. ( )网络时延通常不包括?
A. 排队时延 B. 源代码编译时间
C. 传播时延 D. 传输时延
59. ( )带宽通常表示?
A. 文件的字符编码 B. `CPU` 的缓存容量
C. 单位时间可传输的数据量上限 D. 数据从起点到终点的时间
60. ( )丢包是指?
A. 文件被压缩 B. `CPU` 指令被优化
C. 域名变短 D. 数据包在传输过程中未能到达目的地
61. ( )局域网 `LAN` 一般指?
A. 覆盖较小地理范围的网络 B. 全球范围的所有网络
C. 只包含一台计算机 D. 一种图像格式
62. ( )浏览器输入网址后,通常首先需要通过()获得服务器地址。
A. 编译器链接 B. `DNS` 查询
C. 堆排序 D. 文件压缩
63. ( )子网掩码的作用是?
A. 记录 `CPU` 指令数
B. 表示网页字体
C. 区分 `IP` 地址中的网络部分和主机部分
D. 给文件加密
64. ( )访问网站时出现 `HTTP` 状态码 404,通常表示?
A. 服务器成功返回资源 B. 客户端需要继续发送数据
C. 网络速度为 404Mbps D. 请求的资源未找到
65. ( )`HTTP` 状态码 200 通常表示?
A. 请求成功 B. 永久重定向
C. 资源未找到 D. 服务器内部错误
---
### **题型五: 数据库与信息管理**
66. ( )关系数据库中的一张表由()组成。
A. 树的边 B. 行和列
C. 只有图片 D. 只有程序指令
67. ( )主键的主要作用是?
A. 给网络分配地址 B. 执行图遍历
C. 唯一标识表中的每条记录 D. 压缩所有字段
68. ( )`SQL` 中用于查询数据的关键字是?
A. `DELETE` B. `UPDATE`
C. `DROP` D. `SELECT`
69. ( )`SQL` 中用于筛选行的子句是?
A. `WHERE` B. `ORDER BY`
C. `CREATE` D. `COMMIT`
70. ( )数据库索引的主要作用是?
A. 压缩网络数据包 B. 加快特定条件下的查找
C. 保证所有查询为 $O(1)$ D. 代替数据表保存全部内容
71. ( )外键用于?
A. 确定 `CPU` 主频
B. 保存图像像素
C. 建立表之间的引用关系并维护参照完整性
D. 加密字段
72. ( )事务的原子性表示?
A. 事务只能含一条语句
B. 数据必须存成原子类型
C. 查询一定在常数时间完成
D. 一组操作要么全部成功,要么全部回滚
73. ( )数据库备份的主要目的之一是?
A. 在故障或误操作后恢复数据 B. 提高显示器亮度
C. 改变网络协议 D. 减少 `CPU` 核数
74. 一张学生表中用于唯一标识每名学生的“学号”字段适合作为 ________。
75. ( )执行 `SELECT name FROM student WHERE score >= 90;` 的作用是?
A. 把所有成绩改为 90
B. 创建新数据库
C. 查询成绩不低于 90 分学生的姓名
D. 删除这些学生
---
### **题型六: 字符编码、图像与多媒体**
76. ( )`ASCII` 编码主要用于表示?
A. 任意高清视频
B. 数据库索引
C. `CPU` 指令流水线
D. 基本拉丁字母、数字和控制字符
77. ( )`Unicode` 的主要目标是?
A. 为世界多种文字和符号提供统一编码空间
B. 只编码英文大写字母
C. 压缩所有图片
D. 管理网络路由
78. ( )`UTF-8` 的特点是?
A. 不能在网络传输 B. 变长编码且兼容 `ASCII`
C. 每个字符固定 8 字节 D. 只能表示中文
79. ( )`JPEG` 更适合保存?
A. 纯文本数据库 B. 可执行指令
C. 自然照片 D. 需要完全无损的程序源代码
80. ( )`PNG` 的典型特点是?
A. 只能保存声音 B. 一定比 `JPEG` 小
C. 不包含像素 D. 支持无损压缩和透明通道
81. ( )图像分辨率 $1920 \times 1080$ 表示?
A. 宽方向 1920 个像素、高方向 1080 个像素
B. 每像素 1920 位
C. 文件大小固定 1080KB
D. 帧率为 1920fps
82. ( )颜色深度为 24 位通常意味着每个像素可表示约()种颜色。
A. 1024 B. $2^{24}$
C. 24 D. 256
83. ( )音频采样率越高,在其他条件相同时通常?
A. 量化位数自动变为 1
B. 不影响任何性质
C. 能记录更高频率细节,但数据量更大
D. 数据量更小
84. 标准 `ASCII` 共使用 ________ 位编码。
85. ( )无损压缩的含义是?
A. 解压后可完全恢复原始数据 B. 压缩后不能解压
C. 一定压缩到原来的一半 D. 只适用于声音
---
### **题型七: 程序、编译与数据表示**
86. ( )编译器的主要功能是?
A. 保存数据库备份
B. 把源程序翻译为目标代码或其他等价表示
C. 管理显示器亮度
D. 分配域名
87. ( )链接器的主要作用是?
A. 压缩图片 B. 建立网络路由
C. 把目标文件和库组合并解析符号引用 D. 执行键盘输入
88. ( )语法错误通常在()阶段被发现。
A. 程序正常结束后 B. 硬盘格式化时
C. 网络路由时 D. 编译
89. ( )运行时错误可能由()引起。
A. 数组越界或除以零 B. 正确的注释
C. 合法变量名 D. 正常输出
90. ( )算法的时间复杂度描述?
A. 网络域名长度
B. 输入规模增长时基本操作次数的增长趋势
C. 程序文件的字节数
D. 显示器刷新率
91. ( )算法的空间复杂度描述?
A. 代码颜色
B. 网络时延
C. 随输入规模增长所需额外存储量的趋势
D. 硬盘售价
92. ( )解释执行与编译执行相比,一个典型区别是?
A. 解释器不需要任何程序
B. 编译程序不能运行
C. 两者完全相同
D. 解释器可在运行时逐步处理源代码或中间代码
93. ( )单元测试主要用于?
A. 验证较小程序单元在给定输入下的行为
B. 测量显示器尺寸
C. 配置 `IP` 地址
D. 替代所有人工审查
94. 在大 O 表示法中,$3n^2 + 5n + 7$ 的数量级写作 ________。
95. ( )源程序能够成功编译,但对部分输入输出错误,这类问题通常属于?
A. 文件系统错误 B. 显示器故障
C. 逻辑错误 D. 编译错误
---
### **题型八: 信息安全基础**
96. ( )强密码通常应?
A. 与用户名完全相同 B. 所有网站共用一个
C. 只使用连续数字 D. 长度足够且避免使用易猜个人信息
97. ( )双因素认证的主要作用是?
A. 在密码之外增加另一种身份验证因素 B. 把密码公开给朋友
C. 取消所有登录记录 D. 提高文件压缩率
98. ( )收到要求立即点击陌生链接并输入密码的邮件,应首先警惕?
A. `CPU` 缓存命中 B. 网络钓鱼
C. 图像无损压缩 D. 数据库索引
99. ( )软件安全更新的重要作用之一是?
A. 自动提高网速十倍 B. 把所有文件改成图片
C. 修复已发现的漏洞 D. 永久增加硬盘容量
100. ( )定期离线或异地备份可以降低()造成的数据损失。
​ A. `CPU` 正常运算 B. 合法文本编辑
​ C. 网页排版 D. 硬件故障、误删除或勒索软件
@@ -0,0 +1,154 @@
<center><font size="6.5"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.2 逻辑运算 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | A | A | A | 1 | C | B | 8 | A | A |
| 题号 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | C | A | D | A | 1 | B | A | B | B |
| 题号 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | C | A | 2 | B | C | A | D | A | $(\text{C}3)_{16}$ | C |
| 题号 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | A | D | `x ^ (1 << k)` | B | C | 8 | 9 | D | B |
---
### 详细解析
#### 题型一:布尔值与基础运算
1. **答案:B**
逻辑与 `&&` 运算,只有当两边都为真时结果才为真。`true && false` 的结果是 `false`。
2. **答案:A**
逻辑或 `||` 运算,只要有一边为真,结果就为真。`true || false` 的结果是 `true`。
3. **答案:A**
在 C++ 中,`0` 被视为 `false`,任何非零整数被视为 `true`。逻辑非 `!` 运算符将 `false` 变为 `true`,`true` 变为 `false`。因此 `!0` 的值是 `true`。
4. **答案:A**
在 C++ 中,逻辑与 `&&` 的优先级高于逻辑或 `||`。所以表达式先计算 `false && false`,结果为 `false`。然后计算 `true || false`,结果为 `true`。
5. **答案:1**
异或 $\oplus$ 运算的规则是:当两个操作数不同时,结果为 1(真);相同时,结果为 0(假)。$1 \oplus 0$ 的结果为 1。
6. **答案:C**
根据德摩根律,一个合取式(与运算)的否定等价于其各个分量的否定所构成的析取式(或运算)。即 $\neg(A \wedge B) \equiv \neg A \vee \neg B$。
7. **答案:B**
蕴含式“若 P,则 Q”(记作 $P \rightarrow Q$)的定义是“P 真 Q 假”的情况为假,其他所有情况(P 真 Q 真、P 假 Q 真、P 假 Q 假)均为真。
8. **答案:8**
每个布尔变量有 2 种可能的真值(真或假)。对于 $n$ 个独立的布尔变量,总共的真值组合有 $2^n$ 种。因此,3 个变量有 $2^3 = 8$ 种组合。
#### 题型二:真值表与等价变换
9. **答案:A**
代入值:$(A \vee B)$ 变为 `true || false`,结果是 `true`。$(\neg B \vee C)$ 变为 `true || true`,结果是 `true`。最终 `true && true` 的结果为真。
10. **答案:A**
代入值:$(A \vee C)$ 变为 `false || false`,结果是 `false`。$\neg(A \vee C)$ 变为 `true`。最终 `true && B`(即 `true && true`)的结果为真。
11. **答案:B**
这是逻辑代数中的吸收律:$A \wedge (A \vee B) \equiv A$。无论 $B$ 是真是假,$A \vee B$ 的真值在 $A$ 为假时依赖 $B$,但此时 $A \wedge \dots$ 必定为假。当 $A$ 为真时,$A \vee B$ 必为真,此时 $A \wedge \dots$ 必定为真。所以整个表达式的真值与 $A$ 完全相同。
12. **答案:C**
这也是吸收律:$A \vee (A \wedge B) \equiv A$。当 $A$ 为真时,整个表达式为真。当 $A$ 为假时,$A \wedge B$ 必为假,整个表达式也为假。所以表达式的真值与 $A$ 完全相同。
13. **答案:A**
使用分配律提取公因子 $A$:$(A \wedge B) \vee (A \wedge \neg B) \equiv A \wedge (B \vee \neg B)$。因为 $B \vee \neg B$ 恒为真,所以表达式化简为 $A \wedge \text{true}$,即 $A$。
14. **答案:D**
$P \oplus Q$(异或)的定义是“P 和 Q 中有且仅有一个为真”。选项 D `(P || Q) && !(P && Q)` 意为“P 或 Q 为真,且 P 和 Q 不都为真”,这与异或的定义完全等价。
15. **答案:A**
蕴含式 $P \rightarrow Q$ 的标准等价式是 $\neg P \vee Q$。你可以通过真值表验证两者在所有情况下真值都相同。
16. **答案:1**
逻辑与(合取)$A \wedge B \wedge C$ 为真,当且仅当 $A, B, C$ 三者都为真。在 8 种组合中,只有这一种情况。
17. **答案:B**
使用分配律:$(A \vee B) \wedge (A \vee \neg B) \equiv A \vee (B \wedge \neg B)$。因为 $B \wedge \neg B$ 恒为假,所以表达式化简为 $A \vee \text{false}$,即 $A$。
#### 题型三:C++ 逻辑表达式与短路求值
18. **答案:A**
C++ 的 `&&` 运算符遵循短路求值。首先计算左侧 `x`,其值为 `0` (false)。因为 `false && ...` 的结果必然是 `false`,所以右侧的 `++x` 不会被执行。因此 `x` 的值保持为 `0`。
19. **答案:B**
C++ 的 `||` 运算符同样遵循短路求值。首先计算左侧 `x`,其值为 `1` (true)。因为 `true || ...` 的结果必然是 `true`,所以右侧的 `++x` 不会被执行。因此 `x` 的值保持为 `1`。
20. **答案:B**
在 C++ 中,`int` 到 `bool` 的转换规则是 `0` 为 `false`,非 `0` 为 `true`。`a = 2` (true),`b = 0` (false)。`true && false` 的结果是 `false`,所以 `r` 的值为 `false`。
21. **答案:C**
`!` 运算符优先级很高。`!5` 中,`5` 被视为 `true`,所以 `!5` 结果是 `false`。在与整数 `2` 相加时,`false` 被转换为整数 `0`。所以表达式的值为 `0 + 2 = 2`。
22. **答案:A**
`3 < 5` 的结果是 `true`。`8 % 3` 的结果是 `2`,所以 `2 == 2` 的结果也是 `true`。最终 `true && true` 的结果是 `true`。
23. **答案:2**
当 `x = 3` 时,`(x > 0)` 为 `true`,`(x < 5)` 也为 `true`。在 C++ 中,`bool` 类型的 `true` 在参与算术运算时会被转换为整数 `1`。因此,`y = 1 + 1 = 2`。
24. **答案:B**
由于 `x` 初始为 `0`,`&&` 的左侧表达式 `(x != 0)` 为 `false`。根据短路求值原则,右侧的 `(10 / x > 1)` 不会被计算,从而避免了除以零的运行时错误。变量 `r` 被赋值为 `false`。
25. **答案:C**
首先计算 `||` 左侧的 `(++x == 2)`。预增量 `++x` 使 `x` 变为 `2`,然后比较 `2 == 2`,结果为 `true`。由于 `||` 遵循短路求值,一旦左侧为 `true`,整个表达式的结果就确定为 `true`,右侧的 `(++x == 3)` 不会执行。因此,`x` 的最终值是 `2`。
#### 题型四:按位运算基础
26. **答案:A**
$13 = (1101)_2$,$10 = (1010)_2$。按位与 `&` 运算,上下都为 1 的位才为 1。
`1101 & 1010 = 1000`,即十进制的 `8`。
27. **答案:D**
$13 = (1101)_2$,$10 = (1010)_2$。按位或 `|` 运算,上下只要有 1 的位就为 1。
`1101 | 1010 = 1111`,即十进制的 `15`。
28. **答案:A**
$13 = (1101)_2$,$10 = (1010)_2$。按位异或 `^` 运算,上下不相同的位才为 1。
`1101 ^ 1010 = 0111`,即十进制的 `7`。
29. **答案:$(\text{C}3)_{16}$**
$(3\text{C})_{16}$ 的 8 位二进制是 `00111100`。按位取反 `~` 得到 `11000011`。`1100` 是 $\text{C}$,`0011` 是 $3$。所以结果是 $(\text{C}3)_{16}$。
30. **答案:C**
`5 << 2` 表示将 5 的二进制表示 `101` 左移两位,右侧补 0,得到 `10100`。
$(10100)_2 = 16 + 4 = 20$。左移 $k$ 位相当于乘以 $2^k$。
31. **答案:B**
`40 >> 3` 表示将 40 的二进制表示 `101000` 右移三位,得到 `101`。
$(101)_2 = 4 + 1 = 5$。对非负整数右移 $k$ 位相当于整除 $2^k$。
32. **答案:A**
`1 << k` 会创建一个第 `k` 位为 1,其余位为 0 的掩码。通过按位或 `|` 运算,可以将 `x` 的第 `k` 位强制设为 1,而不改变其他位。
33. **答案:D**
`~(1 << k)` 会创建一个第 `k` 位为 0,其余位全为 1 的掩码。通过按位与 `&` 运算,可以将 `x` 的第 `k` 位强制清零,而不改变其他位。
#### 题型五:位运算技巧与综合
34. **答案:`x ^ (1 << k)`**
按位异或 `^` 的特性是:`a ^ 0 = a`,`a ^ 1 = !a`。`x ^ (1 << k)` 将 `x` 与一个第 `k` 位为 1 的数进行异或,这会翻转第 `k` 位,而其他位因与 0 异或保持不变。
35. **答案:B**
`(x >> k)` 将 `x` 的第 `k` 位移动到最低位(第 0 位)。然后 `& 1` 操作可以提取出这个最低位的值(0 或 1),从而判断原第 `k` 位是 0 还是 1。
36. **答案:C**
表达式 `x &= x - 1` 的作用是消除 `x` 二进制表示中最右边的那个 1。循环的执行次数等于 `x` 的二进制表示中 1 的个数。$44 = 32 + 8 + 4 = (101100)_2$,其中有 3 个 1,所以循环执行 3 次。
37. **答案:8**
表达式 `x & (-x)` 的作用是得到 `x` 二进制表示中最低位的 1 所代表的值(也叫 `lowbit`)。$40 = (101000)_2$。最低位的 1 在第 3 位(从 0 开始计数),其代表的值是 $2^3 = 8$。
38. **答案:9**
按位异或 `^` 满足交换律和结合律,且 $a \oplus a = 0$,$a \oplus 0 = a$。将所有数异或起来,成对出现的数(5 和 7)会两两抵消为 0,最终结果就是那个只出现一次的数,即 9。
39. **答案:D**
一个包含 $n$ 个元素的集合,其子集的数量为 $2^n$。一个 6 位的二进制数,每一位可以取 0 或 1,代表对应元素是否在子集中。因此,总共可以表示 $2^6 = 64$ 个不同的子集。
40. **答案:B**
在 C++ 中,关系运算符 `==` 的优先级高于按位与运算符 `&`。因此,表达式 `a & b == c` 先计算 `b == c`,即 `3 == 1`,结果为 `false`。然后 `false` 转换为整数 `0`,计算 `a & 0`,即 `5 & 0`,结果为 `0`。最后,`0` 被转换为布尔值 `false` 赋给 `r`。
@@ -0,0 +1,154 @@
<center><font size="6.5"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.2 逻辑运算</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### 题型一:布尔值与基础运算
1. ( )逻辑表达式 `true && false` 的值是。
A. true B. false C. 1 D. 无法确定
2. ( )逻辑表达式 `true || false` 的值是。
A. true B. false C. 0 D. 无法确定
3. ( )在 C++ 中,表达式 `!0` 的值是。
A. true B. false C. -1 D. 编译错误
4. ( )在 C++ 中,表达式 `true || false && false` 的值是。
A. true B. false C. 与编译器有关 D. 语法错误
5. 用 $\oplus$ 表示异或运算,则 $1 \oplus 0 =$ \_\_\_\_\_\_\_\_。
6. ( )根据德摩根律,$\neg(A \wedge B)$ 等价于。
A. $\neg A \wedge \neg B$ B. $A \vee B$ C. $\neg A \vee \neg B$ D. $A \wedge \neg B$
7. ( )命题“若 P,则 Q”只在下列哪种情况下为假?
A. P 假,Q 假 B. P 真,Q 假 C. P 假,Q 真 D. P 真,Q 真
8. 三个相互独立的布尔变量 $A, B, C$ 一共有 \_\_\_\_\_\_\_\_ 种不同的真值组合。
---
### 题型二:真值表与等价变换
9. ( )设 `A = true`,`B = false`,`C = true`,则 $(A \vee B) \wedge (\neg B \vee C)$ 的值为。
A. 真 B. 假 C. 与 C 无关,无法判断 D. 表达式不合法
10. ( )设 `A = false`,`B = true`,`C = false`,则 $\neg(A \vee C) \wedge B$ 的值为。
A. 真 B. 假 C. 等于 A D. 等于 C
11. ( )逻辑表达式 $A \wedge (A \vee B)$ 可以化简为。
A. $A \vee B$ B. A C. B D. $A \wedge B$
12. ( )逻辑表达式 $A \vee (A \wedge B)$ 可以化简为。
A. $A \wedge B$ B. B C. A D. $A \vee B$
13. 将 $(A \wedge B) \vee (A \wedge \neg B)$ 化简,结果为 \_\_\_\_\_\_\_\_。
14. ( )$P \oplus Q$ 与下列哪个表达式等价?
A. $P \wedge Q$ B. $P \vee Q$ C. $\neg P \wedge \neg Q$ D. $(P \vee Q) \wedge \neg(P \wedge Q)$
15. ( )蕴含式 $P \rightarrow Q$ 与下列哪个表达式等价?
A. $\neg P \vee Q$ B. $P \vee \neg Q$ C. $P \wedge Q$ D. $\neg P \wedge Q$
16. 在 $A, B, C$ 的全部 8 种真值组合中,使 $A \wedge B \wedge C$ 为真的组合有 \_\_\_\_\_\_\_\_ 种。
17. ( )表达式 $(A \vee B) \wedge (A \vee \neg B)$ 可以化简为。
A. B B. A C. $\neg A$ D. $A \vee B$
---
### 题型三:C++ 逻辑表达式与短路求值
18. ( )执行下列代码后,`x` 的值是。
```cpp
int x = 0; bool y = x && ++x;
```
A. 0 B. 1 C. -1 D. 未定义
19. ( )执行下列代码后,`x` 的值是。
```cpp
int x = 1; bool y = x || ++x;
```
A. 0 B. 1 C. 2 D. 未定义
20. ( )执行 `int a = 2, b = 0; bool r = a && b;` 后,`r` 的值是。
A. true B. false C. 2 D. 编译错误
21. ( )在 C++ 中,表达式 `!5 + 2` 的值是。
A. 0 B. 1 C. 2 D. 3
22. ( )表达式 `3 < 5 && 8 % 3 == 2` 的值是。
A. true B. false C. 2 D. 编译错误
23. 执行 `int x = 3; int y = (x > 0) + (x < 5);` 后,`y =` \_\_\_\_\_\_\_\_。
24. ( )设 `int x = 0;`,执行 `bool r = (x != 0) && (10 / x > 1);`,程序的结果是。
A. 发生除零错误 B. r 为假,且不会计算 10 / x
C. r 为真 D. 无法通过编译
25. ( )执行下列代码后,`x` 的值是。
```cpp
int x = 1; bool r = (++x == 2) || (++x == 3);
```
A. 1 B. 3 C. 2 D. 4
---
### 题型四:按位运算基础
26. ( )十进制整数 13 与 10 进行按位与运算,`13 & 10` 的结果是。
A. 8 B. 10 C. 12 D. 15
27. ( )十进制整数 13 与 10 进行按位或运算,`13 | 10` 的结果是。
A. 7 B. 8 C. 13 D. 15
28. ( )十进制整数 13 与 10 进行按位异或运算,`13 ^ 10` 的结果是。
A. 7 B. 8 C. 13 D. 15
29. 只看低 8 位,$(3\text{C})_{16}$ 按位取反后的结果是 \_\_\_\_\_\_\_\_。
30. ( )对非负整数执行 `5 << 2`,结果是。
A. 7 B. 10 C. 20 D. 25
31. ( )对非负整数执行 `40 >> 3`,结果是。
A. 4 B. 5 C. 8 D. 10
32. ( )若最低位编号为 0,要把整数 `x` 的第 `k` 位设置为 1,应使用。
A. `x | (1 << k)` B. `x & (1 << k)`
C. `x ^ (1 << k)` D. `x & ~(1 << k)`
33. ( )若最低位编号为 0,要把整数 `x` 的第 `k` 位清零,应使用。
A. `x | (1 << k)` B. `x & (1 << k)`
C. `x ^ (1 << k)` D. `x & ~(1 << k)`
---
### 题型五:位运算技巧与综合
34. 若最低位编号为 0,把整数 `x` 的第 `k` 位翻转,可写成 \_\_\_\_\_\_\_\_。
35. ( )若最低位编号为 0,判断非负整数 `x` 的第 `k` 位是否为 1,最直接的表达式是。
A. `x >> (k & 1)` B. `(x >> k) & 1`
C. `x | (1 << k)` D. `x ^ (1 << k)`
36. ( )执行下列循环时,循环体会执行多少次?
```cpp
int x = 44, cnt = 0;
while (x) { x &= x - 1; ++cnt; }
```
A. 2 B. 4 C. 3 D. 5
37. 对正整数 `x = 40`,表达式 `x & (-x)` 的值为 \_\_\_\_\_\_\_\_。
38. 整数序列 5, 7, 5, 9, 7 中,除一个数只出现一次外,其余数都出现两次。把所有数按位异或,结果为 \_\_\_\_\_\_\_\_。
39. ( )用一个 6 位二进制码表示一个含 6 个元素的集合的子集,一共可以表示多少个不同子集?
A. 6 B. 12 C. 36 D. 64
40. ( )执行下列代码后,`r` 的值是。
```cpp
int a = 5, b = 3, c = 1;
bool r = a & b == c;
```
A. true B. false C. 1 D. 编译错误
@@ -0,0 +1,261 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.3 栈、队列 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | A | D | 4 | C | B | A | A | B | C |
| 题号 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | 3, 7, 5 | D | C | A | 3 | C | B | D | 14 |
| 题号 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | 2 | C | A | B | `/-ab+cd` | D | B |
| 题号 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | C | B | C | 3 | A | D | C | 6 | B |
---
### 详细解析
#### 题型一:栈与队列基础
1. **答案:B**
栈(Stack)是一种后进先出(Last-In, First-Out, LIFO)的数据结构。最后被压入(push)的元素总是最先被弹出(pop)。
2. **答案:A**
队列(Queue)是一种先进先出(First-In, First-Out, FIFO)的数据结构。最早进入队列的元素最先离开。
3. **答案:D**
操作过程如下:
1. `push(3)`:栈为 `[3]`。
2. `push(5)`:栈为 `[3, 5]`(5在栈顶)。
3. `pop()`:弹出 5,栈为 `[3]`。
4. `push(7)`:栈为 `[3, 7]`(7在栈顶)。
此时栈顶元素为 7。
4. **答案:4**
操作过程如下:
1. `push(2)`:队列为 `[2]`。
2. `push(4)`:队列为 `[2, 4]`。
3. `push(6)`:队列为 `[2, 4, 6]`。
4. `pop()`:队首元素 2 出队,队列为 `[4, 6]`。
此时队首元素为 4。
5. **答案:C**
“撤销”操作的本质是恢复到上一个状态,这要求我们总是能访问到最近一次的操作记录。栈的“后进先出”特性完美契合这一需求。
6. **答案:B**
广度优先搜索(BFS)按层次遍历图,先访问完距离起点为 k 的所有顶点,再访问距离为 k+1 的顶点。队列的“先进先出”特性保证了这种按层次处理的顺序。
7. **答案:A**
程序在进行函数调用时,会将当前函数的返回地址、局部变量等信息压入一个称为“调用栈”(Call Stack)的内存区域。当被调用的函数返回时,再从栈顶弹出这些信息,恢复到调用前的状态。
8. **答案:A**
操作过程如下:
1. 压入 A, B, C:栈从底到顶为 `[A, B, C]`。
2. 第一次弹出:弹出 C,栈为 `[A, B]`。
3. 第二次弹出:弹出 B,栈为 `[A]`。
此时栈顶元素为 A。
#### 题型二:操作模拟与容量
9. **答案:B**
操作过程如下:
1. 压入 1, 2:栈为 `[1, 2]`。
2. 弹出:弹出 2,栈为 `[1]`。
3. 压入 3, 4:栈为 `[1, 3, 4]`。
4. 弹出:弹出 4,栈为 `[1, 3]`。
结束后,栈中从底到顶的元素是 1, 3。
10. **答案:C**
操作过程如下:
1. 入队 1, 2:队列为 `[1, 2]`。
2. 出队一次:1 出队,队列为 `[2]`。
3. 入队 3, 4:队列为 `[2, 3, 4]`。
4. 再出队一次:2 出队,队列为 `[3, 4]`。
此时队首元素为 3。
11. **答案:B**
模拟过程以找到栈内元素个数的最大值:
1. 为了出 2,需先入 1, 2。栈:`[1, 2]`(容量 2)。
2. 出 2,出 1。栈:`[]`。
3. 为了出 4,需先入 3, 4。栈:`[3, 4]`(容量 2)。
4. 出 4,出 3。栈:`[]`。
5. 入 5,出 5。栈:`[5]`(容量 1)。
整个过程中,栈内最多同时存在 2 个元素,故最小容量为 2。
12. **答案:3, 7, 5**
操作过程如下:
1. 处理 1 (奇):栈 `S = [1]`。
2. 处理 3 (奇):栈 `S = [1, 3]`。
3. 处理 2 (偶):弹出 3,队列 `Q = [3]`。`S = [1]`。
4. 处理 5 (奇):栈 `S = [1, 5]`。
5. 处理 7 (奇):栈 `S = [1, 5, 7]`。
6. 处理 4 (偶):弹出 7,队列 `Q = [3, 7]`。`S = [1, 5]`。
7. 处理 6 (偶):弹出 5,队列 `Q = [3, 7, 5]`。`S = [1]`。
最终队列从队首到队尾为 3, 7, 5。
13. **答案:D**
如果我们用普通数组来实现队列,通常需要两个指针(变量):
* **`front` (头指针)**:指向队头,出队时它往后移。
* **`rear` (尾指针)**:指向队尾的下一个位置,进队时它往后移。
**问题**:随着不断的进队和出队,`front` 和 `rear` 都在往数组的末尾移动。当 `rear` 移动到数组的最后一个位置时,哪怕前面由于出队已经空出了很多位置,新来的元素也放不进去了。这就叫**“假溢出”**。
为了解决“假溢出”,就发明了**循环队列**。
简单来说,就是把数组的头和尾“连起来”变成一个圆环。当 `rear` 走到数组最后面时,如果数组最前面有空位,就让 `rear` 绕回到下标为 0 的位置继续存数据。这个“绕圈”的操作在代码里通常用**取模(求余数 `%`)**来实现。
在循环队列中,假设数组总长度为 `N`。
* **当队列为空时**:`front` 和 `rear` 指向同一个位置,即条件为 `front == rear`。
* **当队列装满时**:如果不空出位置,一直往里装,直到把数组 8 个位置全装满。此时 `rear` 绕了一圈,又追上了 `front`。你会发现,这时候的条件**依然是 `front == rear`**!
这就产生了一个矛盾:**当看到 `front == rear` 时,不知道这代表的是“一个元素都没有”还是“已经完全装满了”!**
为了区分这两种情况,最经典的解决方法就是:**牺牲一个存储空间(始终空出一个位置)**。
规定:
* **队空条件**:仍然是 `front == rear`
* **队满条件**:当 `rear` 再往前走一步就要撞上 `front` 的时候,我们就认为队列满了。
* 数学公式表达为:**(rear + 1) % N == front**
通过这种方法,如果 `rear` 的下一个位置是 `front`,我们就停止进队。因为我们在数组装满的前一刻停手了,所以**永远会有一个位置是空着的**。
当数组长度为 `N` 时,牺牲一个位置来区分队空和队满,意味着队列的最大容量为 `N-1`。因此,最多能存放 $8 - 1 = 7$ 个元素。
14. **答案:C**
循环队列的长度计算公式为 `(rear - front + capacity) % capacity`。代入数值:$(2 - 6 + 8) \pmod 8 = 4$。队列长度为 4。
15. **答案:A**
操作过程如下(`cap=5`):
1. 初始:`front=0, rear=0`。
2. 入队 A, B, C:`rear` 依次变为 1, 2, 3。状态:`front=0, rear=3`。
3. 出队一次:`front` 变为 1。状态:`front=1, rear=3`。
4. 入队 D:`rear` 变为 4。状态:`front=1, rear=4`。
5. 入队 E:`rear` 变为 `(4+1)%5=0`。状态:`front=1, rear=0`。
最终 `(front, rear)` 为 `(1, 0)`。
16. **答案:3**
追踪栈内元素个数:
0 `->` 1 `->` 2 `->` 3 `->` 2 `->` 3 `->` 2 `->` 1 `->` 2 `->` 3 `->` 2。
在此过程中,最大值达到了 3。
#### 题型三:出栈序列与括号匹配
17. **答案:C**
一个出栈序列是合法的,当且仅当对于任意一个元素 `x`,在它出栈之后,所有比它小且还未出栈的元素,必须按从大到小的顺序出栈。
在序列 `3, 1, 2, 5, 4` 中,当 3 出栈后,栈中必然是 `[1, 2]`(2在栈顶)。此时下一个出栈的必须是 2,但序列却是 1。因此,该序列不合法。
18. **答案:B**
模拟过程以找到栈的最大容量需求:
1. 为了出 c,需入 a, b, c。栈:`[a,b,c]`(大小 3)。
2. 出 c, b。栈:`[a]`。
3. 为了出 e,需入 d, e。栈:`[a,d,e]`(大小 3)。
4. 出 e, f (需先入f), d, a。
过程中栈的最大大小为 3。
19. **答案:D**
对于 $n$ 个元素,合法的出栈序列数量由卡特兰数 $C_n = \frac{1}{n+1}\binom{2n}{n}$ 给出。
对于 $n=3$,$C_3 = \frac{1}{4}\binom{6}{3} = \frac{20}{4} = 5$。
注:卡特兰数(Catalan number)是组合数学中一个常在各种计数问题中出现的数列,其前几项为:$(1, 1, 2, 5, 14, 42, 132, 429 \dots)$
* **卡特兰数通项公式**($n \ge 0$):
$$C_n = \frac{1}{n+1}\binom{2n}{n} = \frac{(2n)!}{(n+1)!n!}$$
* $\binom{n}{k}$ 表示从 $n$ 个不同元素中取出 $k$ 个元素的组合方案数,$\binom{2n}{n}$ 即 $C(2n, n)$。
* **卡特兰数递推公式**($n \ge 1, C_0 = 1$):
$$C_n = \frac{4n-2}{n+1} C_{n-1}$$
卡特兰数在组合数学中有着广泛的应用,以下是几种最经典的场景:
* **括号匹配**:
$n$ 对括号的所有合法匹配组合数为 $C_n$。
* **进出栈序列**:
$n$ 个元素依次进栈,合法的出栈序列总数为 $C_n$。
* **二叉树计数**:
$n+1$ 个叶子节点能够构成的不同形态的二叉搜索树(BST)或满二叉树数量为 $C_n$。(*注:$n$ 个节点构成的不同形态二叉树数量也为 $C_n$*)。
* **多边形剖分**:
一个 $n+2$ 边形通过不相交的对角线剖分成三角形的方案数为 $C_n$。
* **网格路径**:
在 $n \times n$ 的方格图中,从左下角走到右上角,且**不越过对角线**的向右和向上走格子路径数为 $C_n$。
20. **答案:14**
根据卡特兰数公式,对于 $n=4$,$C_4 = \frac{1}{5}\binom{8}{4} = \frac{1}{5} \times \frac{8 \times 7 \times 6 \times 5}{4 \times 3 \times 2 \times 1} = 14$。
21. **答案:A**
A. `([{}])`:括号正确配对且嵌套。
B. `([)]`:`[` 与 `)` 不匹配。
C. `(()`:最后一个左括号没有匹配。
D. `{[(]}`:`[` 与 `}` 不匹配。
22. **答案:B**
用栈检查过程:
1. `(` 入栈。栈:`[(`。
2. `[` 入栈。栈:`[(, [`。
3. 遇到 `)`,与栈顶 `[` 不匹配,发现错误。错误发生在第 3 个字符 `)` 处。
23. **答案:C**
追踪栈的深度:可以发现在压入第四个左大括号的时候深度最大为 3。
24. **答案:2**
扫描结束时,栈中还剩 2 个左括号。
#### 题型四:表达式与栈
25. **答案:C**
计算 `3 4 + 2 *`:
1. `3`, `4` 入栈。
2. 遇到 `+`,弹出 4 和 3,计算 $3+4=7$,将 7 入栈。
3. `2` 入栈。
4. 遇到 `*`,弹出 2 和 7,计算 $7 \times 2=14$,将 14 入栈。
最终结果为 14。
26. **答案:A**
计算 `8 2 / 3 -`:
1. `8`, `2` 入栈。
2. 遇到 `/`,弹出 2 和 8,计算 $8 \div 2=4$,将 4 入栈。
3. `3` 入栈。
4. 遇到 `-`,弹出 3 和 4,计算 $4 - 3=1$,将 1 入栈。
最终结果为 1。
27. **答案:B**
`*` 的优先级高于 `+`,所以先计算 `b*c`。`+` 应用于 `a` 和 `b*c` 的结果。因此后缀表达式为 `abc*+`。
28. **答案:`/-ab+cd`**
前缀表达式(波兰表达式)将运算符置于操作数之前。
`a-b` 变为 `-ab`。
`c+d` 变为 `+cd`。
最终的除法变为 `/-ab+cd`。
29. **答案:D**
括号内的 `a+b` 变为 `ab+`。括号内的 `c-d` 变为 `cd-`。最后的 `*` 应用于这两个结果。因此后缀表达式为 `ab+cd-*`。
30. **答案:B**
计算 `5 1 2 + 4 * + 3 -`:
1. `5`, `1`, `2` 入栈。
2. `+`: `1+2=3`,3 入栈。栈:`[5, 3]`。
3. `4` 入栈。栈:`[5, 3, 4]`。
4. `*`: `3*4=12`,12 入栈。栈:`[5, 12]`。
5. `+`: `5+12=17`,17 入栈。栈:`[17]`。
6. `3` 入栈。栈:`[17, 3]`。
7. `-`: `17-3=14`,14 入栈。栈:`[14]`。
结果为 14。
31. **答案:A**
`b+c` 变为 `abc+`。`a*(b+c)` 变为 `abc+*`。最后减 `d`,变为 `abc+*d-`。
32. **答案:C**
前缀表达式从右到左扫描,遇到数字入栈,遇到运算符则弹出两个数计算。
或者递归地看:`+ (* 2 3) (- 8 5)` -> `+ (6) (3)` -> `9`。
#### 题型五:循环队列、双端队列与综合
33. **答案:B**
这是一种均摊分析的经典例子。虽然某一次出队操作可能需要 $O(n)$ 时间(当 `S2` 为空时),但每个元素一生中只会从 `S1` 移到 `S2` 一次。因此,对于 $n$ 次出队操作,总时间复杂度是 $O(n)$,平摊到每次操作上就是 $O(1)$。
34. **答案:C**
为了模拟栈的后进先出,`pop` 操作需要访问到主队列的最后一个元素。这需要将前面的 `n-1` 个元素依次出队并加入辅助队列,这是一个 $O(n)$ 的操作。
35. **答案:3**
双端队列(deque)操作过程:
1. `push_back(1)`:队列为 `[1]`。
2. `push_front(2)`:队列为 `[2, 1]`。
3. `push_back(3)`:队列为 `[2, 1, 3]`。
4. `pop_front()`:弹出 2,队列为 `[1, 3]`。
此时,队首是 1,队尾是 3。
36. **答案:A**
这个问题可以用单调栈解决,但对于小数据可以直接观察:
- 对 2:右侧第一个更大的是 4。
- 对 1:右侧第一个更大的是 4。
- 对 4:右侧没有比它更大的,为 -1。
- 对 3:右侧没有比它更大的,为 -1。
结果序列为 `[4, 4, -1, -1]`。
37. **答案:D**
广度优先搜索(BFS)本质上是按与起点的距离(层数)进行遍历。队列确保了只有在所有距离为 $k$ 的顶点都被访问和处理后,才会开始访问距离为 $k+1$ 的顶点。因此,第一次到达某顶点时,所经过的路径必然是最短的。
38. **答案:C**
同第 13 题,数组长度为 `N`,牺牲一个位置,最大容量为 `N-1`。所以最多可保存 $10 - 1 = 9$ 个元素。
39. **答案:6**
同第 14 题,队列长度为 `(rear - front + capacity) % capacity`。
$(3 - 7 + 10) \pmod{10} = 6$。
40. **答案:B**
同第 19、20 题,合法出栈序列数量由卡特兰数给出。
对于 $n=5$,$C_5 = \frac{1}{6}\binom{10}{5} = \frac{1}{6} \times \frac{10 \times 9 \times 8 \times 7 \times 6}{5 \times 4 \times 3 \times 2 \times 1} = \frac{30240}{6 \times 120} = 42$。
@@ -0,0 +1,151 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.3 栈、队列</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 栈与队列基础**
1. ( )栈中元素的访问原则是?
A. 先进先出 B. 后进先出
C. 随机访问 D. 按关键字从小到大访问
2. ( )队列中元素的访问原则是?
A. 先进先出 B. 后进先出
C. 后进后出 D. 可以从中间任意删除
3. ( )一个空栈依次执行 `push(3)`、`push(5)`、`pop()`、`push(7)`,此时栈顶元素是?
A. 3 B. 5 C. 栈为空 D. 7
4. 一个空队列依次执行 `push(2)`、`push(4)`、`push(6)`、`pop()`,此时队首元素是 \_\_\_\_\_\_\_\_\_\_\_\_。
5. ( )文本编辑器实现“撤销最近一次操作”时,最适合使用的数据结构是?
A. 普通队列 B. 哈希表
C. 栈 D. 邻接矩阵
6. ( )在无权图中进行广度优先搜索时,通常使用()保存待访问顶点。
A. 栈 B. 队列 C. 二叉搜索树 D. 并查集
7. ( )函数递归调用过程中,系统通常使用哪种结构保存返回地址和局部变量?
A. 调用栈 B. 普通队列
C. 散列表 D. 邻接表
8. 空栈依次压入 A, B, C,再连续弹出两次,此时栈顶元素为 \_\_\_\_\_\_\_\_\_\_\_\_。
---
### **题型二: 操作模拟与容量**
9. ( )一个空栈依次执行:压入 1,压入 2,弹出,压入 3,压入 4,弹出。操作结束后,栈中从底到顶的元素是?
A. 1, 4 B. 1, 3 C. 2, 3 D. 1, 2, 3
10. ( )一个空队列依次执行:入队 1, 2,出队一次,入队 3, 4,再出队一次。此时队首元素是?
A. 1 B. 2 C. 3 D. 4
11. ( )元素按 1, 2, 3, 4, 5 的顺序入栈,允许入栈和出栈交替进行。若出栈序列为 2, 1, 4, 3, 5,完成该过程所需的最小栈容量是?
A. 1 B. 2 C. 3 D. 5
12. 依次处理序列 1, 3, 2, 5, 7, 4, 6:遇到奇数就压入栈 S;遇到偶数且 S 非空,就弹出栈顶并加入队列 Q。处理结束后,Q 从队首到队尾为 \_\_\_\_\_\_\_\_\_\_\_\_。
13. ( )用长度为 8 的数组实现循环队列,并约定始终空出一个数组位置来区分“队空”和“队满”,该队列最多能存放()个元素。
A. 6 B. 8 C. 9 D. 7
14. ( )长度为 8 的循环队列中,`front=6`,`rear=2`,其中 `front` 指向队首元素,`rear` 指向下一个入队位置。当前队列长度是?
A. 2 B. 3 C. 4 D. 6
15. ( )长度为 5 的循环队列初始 `front=rear=0`,`rear` 指向下一个入队位置。依次入队 A, B, C,出队一次,再入队 D, E。最终 `(front, rear)` 为?
A. (1, 0) B. (0, 1) C. (1, 4) D. (2, 0)
16. 一个空栈执行操作序列“压、压、压、弹、压、弹、弹、压、压、弹”,操作过程中栈内元素个数的最大值为 \_\_\_\_\_\_\_\_\_\_\_\_。
---
### **题型三: 出栈序列与括号匹配**
17. ( )元素按 1, 2, 3, 4, 5 的顺序入栈,允许入栈和出栈交替进行。下列出栈序列中不可能出现的是?
A. 2, 1, 4, 5, 3 B. 3, 2, 1, 5, 4
C. 3, 1, 2, 5, 4 D. 1, 3, 2, 5, 4
18. ( )元素 a, b, c, d, e, f 依次入栈,要求出栈顺序为 c, b, e, f, d, a。完成该过程所需的最小栈容量为?
A. 2 B. 3 C. 4 D. 6
19. ( )三个互不相同的元素按固定顺序入栈,允许入栈和出栈交替进行,共有多少种不同的合法出栈序列?
A. 3 B. 4 C. 6 D. 5
20. 四个互不相同的元素按固定顺序入栈,允许入栈和出栈交替进行,合法出栈序列共有 \_\_\_\_\_\_\_\_\_\_\_\_种。
21. ( )下列括号序列中,括号匹配正确的是?
A. `([{}])` B. `([)]`
C. `(()` D. `{[(]}`
22. ( )用栈检查括号序列 `([)]` 时,最先发现错误的位置对应字符是?
A. 第二个字符 `[` B. 第三个字符 `)`
C. 第四个字符 `]` D. 扫描结束后才发现
23. ( )从左到右扫描括号串 `(()(()))()`,用栈保存尚未匹配的左括号。扫描过程中栈的最大深度是?
A. 1 B. 2 C. 3 D. 4
24. 扫描括号串 `(()(()`,每个左括号压栈,每个右括号弹栈。扫描结束时栈中还剩 \_\_\_\_\_\_\_\_\_\_\_\_个左括号。
---
### **题型四: 表达式与栈**
25. ( )后缀表达式 `3 4 + 2 *` 的值是?
A. 10 B. 11 C. 14 D. 18
26. ( )后缀表达式 `8 2 / 3 -` 的值是?
A. 1 B. 2 C. 3 D. 5
27. ( )中缀表达式 `a+b*c` 对应的后缀表达式是?
A. `ab+c*` B. `abc*+`
C. `+a*bc` D. `abc+*`
28. 中缀表达式 `(a-b)/(c+d)` 对应的前缀表达式为 \_\_\_\_\_\_\_\_\_\_\_\_。
29. ( )中缀表达式 `(a+b)*(c-d)` 对应的后缀表达式是?
A. `ab+*cd-` B. `*+ab-cd`
C. `abcd+-*` D. `ab+cd-*`
30. ( )后缀表达式 `5 1 2 + 4 * + 3 -` 的值是?
A. 12 B. 14 C. 16 D. 20
31. ( )中缀表达式 `a*(b+c)-d` 对应的后缀表达式是?
A. `abc+*d-` B. `ab*c+d-`
C. `-*a+bcd` D. `abc+ d-*`
32. ( )前缀表达式 `+ * 2 3 - 8 5` 的值是?
A. 6 B. 8 C. 9 D. 11
---
### **题型五: 循环队列、双端队列与综合**
33. ( )用两个栈实现一个队列:入队时压入栈 `S1`;出队时若 `S2` 为空,就把 `S1` 中所有元素依次弹出并压入 `S2`,再从 `S2` 弹出。一次出队操作的均摊时间复杂度是?
A. $O(n)$ B. $O(1)$
C. $O(\log n)$ D. $O(n^2)$
34. ( )用两个队列实现一个栈,规定 `push` 直接把新元素加入主队列;执行 `pop` 时,把除最后一个元素外的所有元素转移到辅助队列,再删除最后一个元素。若当前有 $n$ 个元素,则一次 `pop` 的时间复杂度是?
A. $O(1)$ B. $O(\log n)$
C. $O(n)$ D. $O(n^2)$
35. 一个空双端队列依次执行:`push_back(1)`、`push_front(2)`、`push_back(3)`、`pop_front()`。此时队尾元素为 \_\_\_\_\_\_\_\_\_\_\_\_。
36. ( )对序列 `[2, 1, 4, 3]`,定义每个元素的“右侧第一个更大元素”;若不存在则记为 -1。所得序列是?
A. `[4, 4, -1, -1]` B. `[4, 2, -1, 4]`
C. `[1, 4, 3, -1]` D. `[-1, 4, -1, -1]`
37. ( )在边权均为 1 的图中,广度优先搜索第一次访问到某顶点时就得到了从起点到该顶点的最短路,根本原因是?
A. 每个顶点只允许有一个前驱
B. 队列会自动按顶点编号排序
C. 图中不存在环
D. 队列保证按距离起点从小到大的层次扩展
38. ( )长度为 10 的数组实现循环队列,采用“空出一个位置”方案。队列最多可同时保存()个元素。
A. 8 B. 10 C. 9 D. 11
39. 长度为 10 的循环队列中,`front=7`,`rear=3`,其中 `rear` 指向下一个入队位置。当前队列长度为 \_\_\_\_\_\_\_\_\_\_\_\_。
40. ( )五个互不相同的元素按固定顺序入栈,允许入栈和出栈交替进行,不限制栈容量。合法出栈序列共有()种。
A. 32 B. 42 C. 60 D. 120
@@ -0,0 +1,113 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.4 二叉树的遍历 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | 5 | A | B | 19 | D | A | B |
| 题号 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | C | D | A | B | C | D | A | ABCDEF | C | MHTKPWJ |
| 题号 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | D | A | B | C | 3 | A | B |
| 题号 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | C | 9 | A | B | 8 | D | A | B | 25 | D |
---
### 详细解析
#### 题型一:二叉树基本性质
1. **答案:A**
若根结点位于第 1 层,那么每向下一层,每个结点至多产生两个孩子,因此该层的最大结点数是上一层的两倍。第 1 层最多 $2^0 = 1$ 个结点,第 2 层最多 $2^1 = 2$ 个结点,通过归纳可得第 $i$ 层至多有 $2^{i-1}$ 个结点。
2. **答案:B**
当二叉树的结点数最多时,它是一棵满二叉树,每一层都达到了最大容量。高度为 $h$ 的满二叉树总结点数是各层结点数之和,构成一个等比数列 $1 + 2 + \dots + 2^{h-1}$,其和为 $2^h - 1$。
3. **答案:C**
在任意二叉树中,设度为 0、1、2 的结点数分别为 $n_0, n_1, n_2$,总结点数 $n = n_0 + n_1 + n_2$。树的边数等于 $n - 1$。从另一个角度看,边由度为 1 和度为 2 的结点贡献,总边数也等于 $n_1 + 2n_2$。因此,我们有等式 $n_0 + n_1 + n_2 - 1 = n_1 + 2n_2$。化简后得到 $n_0 = n_2 + 1$,即叶结点数比度为 2 的结点数多 1。
4. **答案:5**
高度为 $h$ 的满二叉树有 $2^h - 1$ 个结点。已知一棵完全二叉树的结点总数为 31,由于 $31 = 2^5 - 1$,这棵树恰好是一棵五层满二叉树,因此其高度为 5。
5. **答案:A**
对于一棵有 $n$ 个结点的完全二叉树(按 1 至 $n$ 编号),考虑最大的节点 $n$,它的父亲节点 $\lfloor n/2 \rfloor$, 故为所有编号大于 $\lfloor n/2 \rfloor$ 的结点都是叶结点。本题中 $n=100$,则编号从 $\lfloor 100/2 \rfloor + 1 = 51$ 到 100 的结点都是叶结点,共 $100 - 51 + 1 = 50$ 个。
6. **答案:B**
在从 1 开始编号的完全二叉树中,下标为 $i$ ($i > 1$) 的结点的父结点下标为 $\lfloor i/2 \rfloor$。因此,下标为 13 的结点的父结点下标为 $\lfloor 13/2 \rfloor = 6$。
7. **答案:19**
在从 1 开始编号的完全二叉树中,下标为 $i$ 的结点的左、右孩子下标分别为 $2i$ 和 $2i + 1$。因此,下标为 9 的结点的右孩子下标为 $2 \times 9 + 1 = 19$。
8. **答案:D**
根据性质 $n_0 = n_2 + 1$,已知叶结点数 $n_0 = 12$,可得度为 2 的结点数 $n_2 = 11$。又已知度为 1 的结点数 $n_1 = 7$。总结点数 $n = n_0 + n_1 + n_2 = 12 + 7 + 11 = 30$。
#### 题型二:遍历序列判断与求解
9. **答案:A**
前序遍历的顺序是“根-左-右”。从根结点 A 开始,递归访问:A -> B (A的左子树) -> D (B的左子树) -> E (B的右子树) -> C (A的右子树) -> F (C的右子树)。最终序列为 `ABDECF`。
10. **答案:B**
中序遍历的顺序是“左-根-右”。对根结点 A 应用该规则:先访问左子树 B,再访问 A,最后访问右子树 C。对 B 递归应用:先访问左子树 D,再访问 B,最后访问右子树 E,得到 `DBE`。对 C 递归应用:C 没有左子树,先访问 C,再访问右子树 F,得到 `CF`。组合起来得到 `DBEACF`。
11. **答案:C**
前序遍历顺序是“根-左-右”。从根 M 开始递归访问:M -> H -> K -> J -> T -> P -> W。序列为 `MHKJTPW`。
12. **答案:D**
中序遍历顺序是“左-根-右”。递归应用该规则:H -> J -> K -> M -> P -> T -> W。序列为 `HJKMPTW`。
13. **答案:A**
前序遍历顺序是“根-左-右”。从根 R 开始递归访问:R -> L -> D -> F -> X -> T -> Z。序列为 `RLDFXTZ`。
14. **答案:B**
中序遍历顺序是“左-根-右”。递归应用该规则:D -> F -> L -> R -> T -> X -> Z。序列为 `DFLRTXZ`。
15. **答案:C**
前序遍历顺序是“根-左-右”。从根 G 开始递归访问,得到序列 `GCAEDFNJQ`。
16. **答案:D**
中序遍历顺序是“左-根-右”。递归应用该规则,得到序列 `ACDEFGJNQ`。
17. **答案:A**
已知前序遍历为 `ABDECF`,中序遍历为 `DBEACF`。根据前序,根是 A。在中序中,`DBE` 在 A 左侧(左子树),`CF` 在 A 右侧(右子树)。对左子树 `DBE`,其前序为 `BDEC`,根为 B,左子树为 `D`,右子树为 `E`。对右子树 `CF`,其前序为 `CF`,根为 C,右子树为 `F`。确定树结构后,其后序遍历(左-右-根)为 `DEBFCA`。
18. **答案:ABCDEF**
根据上一题还原的树结构,进行层序遍历(从上到下,从左到右),访问顺序为 `A` -> `B, C` -> `D, E, F`。序列为 `ABCDEF`。
19. **答案:C**
已知前序遍历为 `MHKJTPW`,中序遍历为 `HJKMPTW`。根是 M,左子树中序为 `HJK`,右子树中序为 `PTW`。递归还原树结构后,进行后序遍历(左-右-根),得到 `JKHPWTM`。
20. **答案:MHTKPWJ**
根据上一题还原的树结构,进行层序遍历,访问顺序为 `M` -> `H, T` -> `K, P, W` -> `J`。序列为 `MHTKPWJ`。
#### 题型三:由遍历序列重建二叉树
21. **答案:A**
前序遍历 `ABDECF` 的第一个元素 `A` 是根。在中序遍历 `DBEACF` 中,`A` 左侧的 `DBE` 是左子树,右侧的 `CF` 是右子树。对左子树,其前序为 `BDEC`,中序为 `DBE`,可确定根为 `B`,左孩子为 `D`,右孩子为`E`。对右子树,其前序为 `CF`,中序为 `CF`,根为 `C`,右孩子为 `F`。树结构确定后,后序遍历(左-右-根)为 `DEBFCA`。
22. **答案:B**
前序遍历 `MHKJTPW` 的第一个元素 `M` 是根。在中序遍历 `HJKMPTW` 中,`HJK` 是左子树,`PTW` 是右子树。递归分析可还原整棵树。最后进行后序遍历(左-右-根),得到 `JKHPWTM`。
23. **答案:C**
前序遍历 `RLDFXTZ` 的第一个元素 `R` 是根。在中序遍历 `DFLRTXZ` 中,`DFL` 是左子树,`TXZ` 是右子树。递归还原树结构后,进行后序遍历(左-右-根),得到 `FDLTZXR`。
24. **答案:D**
前序遍历 `GCAEDFNJQ` 的第一个元素 `G` 是根。在中序遍历 `ACDEFGJNQ` 中,`ACDEF` 是左子树,`JNQ` 是右子树。递归还原树结构后,进行后序遍历(左-右-根),得到 `ADFECJQNG`。
25. **答案:A**
后序遍历 `DEBFCA` 的最后一个元素 `A` 是根。在中序遍历 `DBEACF` 中,`A` 左侧的 `DBE` 是左子树,右侧的 `CF` 是右子树。递归还原树结构后,进行前序遍历(根-左-右),得到 `ABDECF`。
26. **答案:B**
后序遍历 `JKHPWTM` 的最后一个元素 `M` 是根。在中序遍历 `HJKMPTW` 中,`HJK` 是左子树,`PTW` 是右子树。递归还原树结构后,进行前序遍历(根-左-右),得到 `MHKJTPW`。
27. **答案:C**
后序遍历 `FDLTZXR` 的最后一个元素 `R` 是根。在中序遍历 `DFLRTXZ` 中,`DFL` 是左子树,`TXZ` 是右子树。递归还原树结构后,进行前序遍历(根-左-右),得到 `RLDFXTZ`。
28. **答案:3**
前序遍历 `ABCDEFG` 的第一个元素 `A` 是根。在中序遍历 `CBDAFEG` 中,位于 `A` 右侧的元素 `FEG` 构成了根结点的右子树。因此,右子树共有 3 个结点。
#### 题型四:遍历性质与综合
29. **答案:A**
前序遍历的顺序是“根-左-右”,中序遍历是“左-根-右”。要使两个序列完全相同,对于任何一个结点(子树的根),都必须先访问它自己,然后不能有左子树(否则中序会先访问左子树),只能有右子树。因此,该树一定满足每个非叶结点都没有左孩子,形成一条向右的链。
30. **答案:B**
前序遍历的第一个元素是根,而后序遍历的最后一个元素是根。如果序列长度大于 1 且结点值互不相同,那么这两个位置的元素一定不同,序列也就不可能完全相同。因此,只有当树为空或只有一个结点时,前序和后序遍历才可能相同。
31. **答案:C**
前序遍历(根-左-右)和后序遍历(左-右-根)都能唯一确定根。但对于只有一个孩子的结点(例如根 A 只有一个孩子 B),无论 B 是左孩子还是右孩子,前序都是 `AB`,后序都是 `BA`。由于无法区分 B 的左右属性,导致无法唯一确定树的形态。
32. **答案:9**
一棵有 $n$ 个结点的二叉树,总共有 $2n$ 个指针域(每个结点两个)。其中有 $n-1$ 个指针域被用来指向孩子结点(对应 $n-1$ 条边)。剩下的指针域都是空的。所以空指针域的总数为 $2n - (n-1) = n+1$。对于 $n=8$,空指针域数量为 $8+1 = 9$。
33. **答案:A**
非递归实现中序遍历时,需要先沿着左子树一路访问到底,这个过程类似递归的深入。当一个结点的左子树访问完毕后,需要回溯到该结点并访问它,然后再处理其右子树。这种“后进先出”的回溯行为正好可以用栈来模拟。
34. **答案:B**
层序遍历(或广度优先遍历)的特点是按层次处理结点。处理完第 $k$ 层的所有结点后,再统一处理第 $k+1$ 层的所有结点。队列的“先进先出”(FIFO)特性完美地支持了这种按发现顺序列队、按出队顺序处理的模式。
35. **答案:8**
前序 `ABCD` 和后序 `DCBA` 表明该树是一条链。树中共有 A, B, C, D 四个结点。除叶结点外的 A, B, C 三个非叶结点,它们都只有一个孩子。每个孩子的方向可以是左或右,两种选择。这三个结点的方向选择是相互独立的,因此总共的形态数为 $2 \times 2 \times 2 = 2^3 = 8$ 种。
36. **答案:D**
一般情况下,仅有前序和后序遍历无法唯一确定一棵二叉树,因为存在单孩子结点的左右方向歧义。但对于满二叉树,每个非叶结点都恰好有两个孩子,不存在单孩子结点。因此,歧义源消失,可以通过前序和后序唯一确定一棵满二叉树。
37. **答案:A**
满二叉树的结点数 $n$ 与高度 $h$ 满足关系 $n = 2^h - 1$。已知 $n = 127$,解方程 $127 = 2^h - 1$,得到 $2^h = 128 = 2^7$,因此高度 $h=7$。
38. **答案:B**
表达式树的内部结点是运算符,叶结点是操作数。对其进行中序遍历,访问顺序是“左子树(左操作数)- 根(运算符)- 右子树(右操作数)”,这正好对应中缀表达式的形式。为了保持原有的运算优先级,通常需要在遍历过程中添加适当的括号。
39. **答案:25**
在从 1 开始编号的完全二叉树中,所有编号在 $1$ 到 $\lfloor n/2 \rfloor$ 之间的结点都是非叶结点(分支结点)。对于 $n=50$,最后一个非叶结点的下标是 $\lfloor 50/2 \rfloor = 25$。
40. **答案:D**
后序 `DEBFGCA` 的末尾 `A` 是根。中序 `DBEAFCG` 中,`A` 左边 `DBE` 是左子树,右边 `FCG` 是右子树。对左子树,后序 `DEB`,中序 `DBE`,根为 `B`,左 `D` 右 `E`。对右子树,后序 `FGC`(去掉 `A`和左子树部分`DEB`),中序 `FCG`,根为 `C`,左 `F` 右 `G`。还原的树进行层序遍历,得到 `A` -> `B, C` -> `D, E, F, G`。序列为 `ABCDEFG`。
@@ -0,0 +1,166 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.4 二叉树的遍历</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 二叉树基本性质**
1. ( )一棵非空二叉树中,第 $i$ 层至多有多少个结点?
A. $2^{i-1}$ B. $2^i$
C. $i^2$ D. $2i$
2. ( )根结点高度记为 1。高度为 $h$ 的二叉树至多有多少个结点?
A. $h^2$ B. $2^h - 1$
C. $2^{h-1}$ D. $2^{h+1} - 1$
3. *( )一棵二叉树有 $n_0$ 个叶结点、$n_2$ 个度为 2 的结点,则必有?
A. $n_0 = 2n_2$ B. $n_2 = n_0 + 1$
C. $n_0 = n_2 + 1$ D. $n_0 = n_2$
4. 一棵完全二叉树共有 31 个结点,其高度为 \_\_\_\_\_\_\_\_\_\_\_\_。
5. ( )一棵完全二叉树共有 100 个结点,按从 1 开始的数组下标存储,叶结点的个数是?
A. 50 B. 49 C. 51 D. 64
6. ( )完全二叉树按数组下标从 1 存储。下标为 13 的结点若有父结点,其父结点下标为?
A. 26 B. 6 C. 5 D. 7
7. 完全二叉树按数组下标从 1 存储,下标为 9 的结点的右孩子下标为 \_\_\_\_\_\_\_\_\_\_\_\_。
8. ( )一棵二叉树有 12 个叶结点和 7 个度为 1 的结点,则总结点数为?
A. 19 B. 24 C. 31 D. 30
---
### **题型二: 遍历序列判断与求解**
9. ( )某二叉树的结构为:A 为根,各结点左右孩子依次为 `A:(B,C)`,`B:(D,E)`,`C:(空,F)`,`D:(空, 空)`,`E:(空, 空)`,`F:(空, 空)`。其前序遍历为?
A. `ABDECF` B. `DBEACF`
C. `DEBFCA` D. `ABCDEF`
10. ( )上述二叉树(根为 A,各结点左右孩子依次为 `A:(B,C)`,`B:(D,E)`,`C:(空,F)`,`D:(空, 空)`,`E:(空, 空)`,`F:(空, 空)`)的中序遍历为?
A. `ABCDEF` B. `DBEACF`
C. `ABDECF` D. `DEBFCA`
11. ( )某二叉树的结构为:M 为根,各结点左右孩子依次为 `M:(H,T)`,`H:(空,K)`,`K:(J, 空)`,`J:(空, 空)`,`T:(P,W)`,`P:(空, 空)`,`W:(空, 空)`。其前序遍历为?
A. `JKHPWTM` B. `MHTKPWJ`
C. `MHKJTPW` D. `HJKMPTW`
12. ( )上述二叉树(根为 M,各结点左右孩子依次为 `M:(H,T)`,`H:(空,K)`,`K:(J, 空)`,`J:(空, 空)`,`T:(P,W)`,`P:(空, 空)`,`W:(空, 空)`)的中序遍历为?
A. `MHKJTPW` B. `JKHPWTM`
C. `MHTKPWJ` D. `HJKMPTW`
13. ( )某二叉树的结构为:R 为根,各结点左右孩子依次为 `R:(L,X)`,`L:(D, 空)`,`D:(空,F)`,`F:(空, 空)`,`X:(T,Z)`,`T:(空, 空)`,`Z:(空, 空)`。其前序遍历为?
A. `RLDFXTZ` B. `DFLRTXZ`
C. `FDLTZXR` D. `RLXDTZF`
14. ( )上述二叉树(根为 R,各结点左右孩子依次为 `R:(L,X)`,`L:(D, 空)`,`D:(空,F)`,`F:(空, 空)`,`X:(T,Z)`,`T:(空, 空)`,`Z:(空, 空)`)的中序遍历为?
A. `RLXDTZF` B. `DFLRTXZ`
C. `RLDFXTZ` D. `FDLTZXR`
15. ( )某二叉树的结构为:G 为根,各结点左右孩子依次为 `G:(C,N)`,`C:(A,E)`,`A:(空, 空)`,`E:(D,F)`,`D:(空, 空)`,`F:(空, 空)`,`N:(J,Q)`,`J:(空, 空)`,`Q:(空, 空)`。其前序遍历为?
A. `ADFECJQNG` B. `GCNAEJQDF`
C. `GCAEDFNJQ` D. `ACDEFGJNQ`
16. ( )上述二叉树(根为 G,各结点左右孩子依次为 `G:(C,N)`,`C:(A,E)`,`A:(空, 空)`,`E:(D,F)`,`D:(空, 空)`,`F:(空, 空)`,`N:(J,Q)`,`J:(空, 空)`,`Q:(空, 空)`)的中序遍历为?
A. `GCAEDFNJQ` B. `ADFECJQNG`
C. `GCNAEJQDF` D. `ACDEFGJNQ`
17. ( )已知该树前序为 `ABDECF`、中序为 `DBEACF`,其后序遍历是?
A. `DEBFCA` B. `ABDECF`
C. `DBEACF` D. `ABCDEF`
18. 已知该树前序为 `ABDECF`、中序为 `DBEACF`,其层序遍历为 \_\_\_\_\_\_\_\_\_\_\_\_。
19. ( )已知该树前序为 `MHKJTPW`、中序为 `HJKMPTW`,其后序遍历是?
A. `HJKMPTW` B. `MHTKPWJ`
C. `JKHPWTM` D. `MHKJTPW`
20. 已知该树前序为 `MHKJTPW`、中序为 `HJKMPTW`,其层序遍历为 \_\_\_\_\_\_\_\_\_\_\_\_。
---
### **题型三: 由遍历序列重建二叉树**
21. ( )某二叉树的前序遍历为 `ABDECF`,中序遍历为 `DBEACF`,则后序遍历为?
A. `DEBFCA` B. `ACFBED`
C. `DBEACF` D. `ABDECF`
22. ( )某二叉树的前序遍历为 `MHKJTPW`,中序遍历为 `HJKMPTW`,则后序遍历为?
A. `MHKJTPW` B. `JKHPWTM`
C. `MTWPHKJ` D. `HJKMPTW`
23. ( )某二叉树的前序遍历为 `RLDFXTZ`,中序遍历为 `DFLRTXZ`,则后序遍历为?
A. `DFLRTXZ` B. `RLDFXTZ`
C. `FDLTZXR` D. `RXZTLDF`
24. ( )某二叉树的前序遍历为 `GCAEDFNJQ`,中序遍历为 `ACDEFGJNQ`,则后序遍历为?
A. `GNQJCEFDA` B. `ACDEFGJNQ`
C. `GCAEDFNJQ` D. `ADFECJQNG`
25. ( )某二叉树的后序遍历为 `DEBFCA`,中序遍历为 `DBEACF`,则前序遍历为?
A. `ABDECF` B. `DEBFCA`
C. `DBEACF` D. `FCEDBA`
26. ( )某二叉树的后序遍历为 `JKHPWTM`,中序遍历为 `HJKMPTW`,则前序遍历为?
A. `WPTJKHM` B. `MHKJTPW`
C. `JKHPWTM` D. `HJKMPTW`
27. ( )某二叉树的后序遍历为 `FDLTZXR`,中序遍历为 `DFLRTXZ`,则前序遍历为?
A. `DFLRTXZ` B. `ZTXFDLR`
C. `RLDFXTZ` D. `FDLTZXR`
28. 某二叉树前序遍历为 `ABCDEFG`,中序遍历为 `CBDAFEG`。根结点的右子树共有 \_\_\_\_\_\_\_\_\_\_\_\_个结点。
---
### **题型四: 遍历性质与综合**
29. ( )若一棵结点值互不相同的非空二叉树,其前序遍历与中序遍历完全相同,则该树一定满足?
A. 每个非叶结点都没有左孩子 B. 每个非叶结点都没有右孩子
C. 一定是满二叉树 D. 左右子树结点数始终相等
30. ( )若一棵结点值互不相同的二叉树,其前序遍历与后序遍历完全相同,则?
A. 该树是完全二叉树 B. 该树只有一个结点
C. 该树是一条左链 D. 该树是一条右链
31. ( )仅给出一棵二叉树的前序遍历和后序遍历,通常不能唯一确定该树,主要原因是?
A. 无法确定结点总数
B. 无法确定叶结点个数
C. 无法判断只有一个孩子的结点,其孩子位于左侧还是右侧
D. 无法确定根结点
32. 一棵含 8 个结点的二叉树,其空指针域总数为 \_\_\_\_\_\_\_\_\_\_\_\_。
33. ( )用非递归方式实现二叉树中序遍历时,通常需要使用?
A. 栈 B. 普通队列
C. 并查集 D. 哈希表
34. ( )用层序遍历访问二叉树时,通常需要使用?
A. 二叉搜索树 B. 队列
C. 栈 D. 优先队列
35. 一棵二叉树的前序为 `ABCD`,后序为 `DCBA`。若已知每个非叶结点都只有一个孩子,则可能的不同二叉树形态共有 ________ 种。
36. ( )一棵满二叉树共有 15 个结点,其前序序列和后序序列能否唯一确定该树?
A. 不可以,因为任何二叉树都不能由前序和后序确定
B. 只有结点数为奇数时可以
C. 只有再给出层序遍历时才可以
D. 可以,因为满二叉树中每个非叶结点都有两个孩子
37. ( )一棵满二叉树共有 127 个结点,其高度(根高度为 1)为?
A. 7 B. 6 C. 8 D. 127
38. ( )表达式树的中序遍历通常对应?
A. 层序表达式
B. 带适当括号的中缀表达式
C. 前缀表达式
D. 后缀表达式
39. 一棵完全二叉树共有 50 个结点,按数组下标从 1 存储,最后一个非叶结点下标为 \_\_\_\_\_\_\_\_\_\_\_\_。
40. ( )已知某二叉树中序遍历为 `DBEAFCG`,后序遍历为 `DEBFGCA`,其层序遍历为?
A. `ABDECFG` B. `DBEAFCG`
C. `DEBFGCA` D. `ABCDEFG`
@@ -0,0 +1,135 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.5 哈夫曼树和哈夫曼编码 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | 7 | A | B | C | D | A |
| 题号 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | D | B | D | B | 2.38 | 1.75 | 2.24 | 2.2 |
| 题号 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | D | A | B | C | B | `0001100` | D | A | B |
---
### 详细解析
#### **题型一: 基本概念与性质**
1. **答案:A**
哈夫曼算法采用贪心策略:在构造过程中,总是选取当前森林中权值最小的两棵树(根结点)进行合并,形成一棵新树。这样可以确保权值较小的叶子结点处于树的较深层次,从而使得最终的带权路径长度最小。
2. **答案:B**
哈夫曼编码是一种**前缀码**。前缀码的核心性质是:集合中任何一个码字都不是另一个码字的前缀。这一性质保证了在从左到右连续读取比特流时,可以唯一且无歧义地进行解码。
3. **答案:C**
哈夫曼树是一棵严格二叉树(即每个非叶结点都恰好有两个孩子)。对于一棵有 $n$ 个叶结点的严格二叉树,其内部(非叶)结点数必为 $n-1$。因此,总结点数为:叶结点数 + 内部结点数 = $n + (n-1) = 2n-1$。
4. **答案:7**
根据上一题的性质,当叶结点数为 8 时,非叶结点数(内部结点数)为 $8 - 1 = 7$。
5. **答案:A**
哈夫曼编码的目标是最小化加权平均码长。为了实现这一目标,算法会为出现频率(权值)越高的字符分配越短的编码。在某些特定的权值分布下,高频字符的编码长度可能与某个低频字符相等,但绝不会比它更长。
6. **答案:B**
哈夫曼树的带权路径长度(Weighted Path Length, WPL)是衡量其编码效率的指标。它的计算方法是:将所有**叶结点**的权值(代表字符频率)乘以其各自到根结点的路径长度(即深度,也对应其编码长度),然后将所有这些乘积求和。
**哈夫曼树的带权路径长度也可以理解为合并果子的那道题目**,每次取权值最小的两个结点进行合并,合并的代价就是权值之和,最后将每次合并的代价累加在一起就是最终的代价,其实这个过程求也就是哈夫曼树的带权路径长度(WPL)。
#### **题型二: 构造过程与带权路径长度**
7. **答案:C**
一种快速计算 WPL 的方法是:**WPL 等于所有构造过程中产生的非叶(中间)结点的权值之和**。
- 权值集合:{5, 7, 10, 15}
- 第1步:合并最小的 5 和 7,产生新权值 **12**。森林变为 {10, 12, 15}。
- 第2步:合并最小的 10 和 12,产生新权值 **22**。森林变为 {15, 22}。
- 第3步:合并 15 和 22,产生根结点权值 **37**。
- WPL = $12 + 22 + 37 = 71$。
8. **答案:D**
- 权值集合:{2, 3, 7, 9, 18}
- 合并 (2, 3) -> **5**。森林:{5, 7, 9, 18}。
- 合并 (5, 7) -> **12**。森林:{9, 12, 18}。
- 合并 (9, 12) -> **21**。森林:{18, 21}。
- 合并 (18, 21) -> **39**。
- WPL = $5 + 12 + 21 + 39 = 77$。
9. **答案:A**
- 权值集合:{4, 6, 8, 12, 20}
- 合并 (4, 6) -> **10**。森林:{8, 10, 12, 20}。
- 合并 (8, 10) -> **18**。森林:{12, 18, 20}。
- 合并 (12, 18) -> **30**。森林:{20, 30}。
- 合并 (20, 30) -> **50**。
- WPL = $10 + 18 + 30 + 50 = 108$。
10. **答案:D**
哈夫曼算法的第一步是选取权值最小的两个结点进行合并。在集合 {4, 6, 9, 13} 中,最小的两个权值是 4 和 6。它们合并后产生的新权值为 $4 + 6 = 10$。
#### **题型三: 编码长度与压缩率**
11. **答案:B**
在哈夫曼树的构造过程中,权值最大的结点通常是在最后几步才参与合并。对于集合 {5, 9, 12, 13, 16, 45},权值 45 远大于其他权值之和的一半,它会在最后一步与其余所有元素合并成的子树的根结点进行合并。因此,它会直接作为根结点的孩子,深度为 1,即编码长度为 1。
12. **答案:D**
- 权值集合:{2, 3, 5, 10}
- (2, 3) -> 5。森林:{5, 5, 10}。
- (5, 5) -> 10。森林:{10, 10}。
- (10, 10) -> 20。
- 原始权值 10 在最后一步参与合并,深度为 1,编码长度为 1。
13. **答案:B**
- 权值集合:{1, 2, 4, 8, 16}
- (1, 2) -> 3。 (3, 4) -> 7。 (7, 8) -> 15。 (15, 16) -> 31。
- 原始权值 16 在最后一步参与合并,深度为 1,编码长度为 1。
14. **答案:2.38**
- 总权重 $W = 3+4+6+8+12+20 = 53$。
- WPL = $(3+4) + (6+7) + (8+12) + (13+20) + (20+33) = 7+13+20+33+53 = 126$。
- 加权平均码长 = WPL / W = $126 / 53 \approx 2.377$。
15. **答案:1.75**
- 总权重 $W = 2+3+5+10 = 20$。
- WPL = $(2+3) + (5+5) + (10+10) = 5+10+20 = 35$。
- 加权平均码长 = $35 / 20 = 1.75$。
16. **答案:2.24**
- 总权重 $W = 100$。
- WPL = $(5+9) + (12+13) + (14+16) + (25+30) + (45+55) = 14+25+30+55+100 = 224$。
- 加权平均码长 = $224 / 100 = 2.24$。
17. **答案:2.2**
- 总权重 $W = 4+7+10+15+19=55$。
- WPL = $(4+7)+(10+11)+(15+19)+(21+34) = 11+21+34+55 = 121$。
- 加权平均码长 = $121 / 55 = 2.2$。
#### **题型四: 前缀码与解码**
18. **答案:D**
在 `{0, 10, 110, 111}` 中,检查任意一个码字是否是另一个码字的前缀:`0` 不是 `10`、`110` 或 `111` 的前缀;`10` 不是 `110` 或 `111` 的前缀。没有前缀冲突,所以它是前缀码。
19. **答案:A**
在 `{0, 01, 10, 11}` 中,`0` 是 `01` 的前缀,违反了前缀码的定义。
20. **答案:B**
在 `{00, 01, 10, 110}` 中,检查可知没有一个码字是另一个码字的前缀,所以是前缀码。
21. **答案:C**
在 `{1, 00, 010, 011}` 中,检查可知没有一个码字是另一个码字的前缀,所以是前缀码。
22. **答案:B**
- 从比特串 `0101110` 的开头开始匹配:
- `0` -> 匹配 `A`。剩余 `101110`。
- `10` -> 匹配 `B`。剩余 `1110`。
- `111` -> 匹配 `D`。剩余 `0`。
- `0` -> 匹配 `A`。
- 解码结果为 `ABDA`。
23. **答案:`0001100`**
- `A` -> `00`
- `B` -> `01`
- `C` -> `1`
- `A` -> `00`
- 拼接起来得到 `0001100`。
#### **题型五: 综合应用**
24. **答案:D**
- **定长编码**:有 4 种字符,需要 $\lceil \log_2 4 \rceil = 2$ 位。总字符数 $40+30+20+10 = 100$。总比特数 = $100 \times 2 = 200$。
- **哈夫曼编码**:对权值 {10, 20, 30, 40} 构造哈夫曼树,其 WPL = $(10+20) + (30+30) + (40+60) = 30 + 60 + 100 = 190$。WPL 即为编码整个文件的总比特数。
25. **答案:A**
当 $n$ 个字符的权值完全相同时,并且 $n$ 是 2 的幂(如 $n=8=2^3$),构造出的哈夫曼树是一棵完全二叉树。所有叶结点都位于同一层,深度为 $\log_2 n$。因此,每个字符的码长都等于 $\log_2 8 = 3$。
26. **答案:B**
- 权值集合:{1, 1, 1, 1, 100}
- 构造过程会优先合并 4 个权值为 1 的结点。
- (1, 1) -> 2。森林:{1, 1, 2, 100}。
- (1, 1) -> 2。森林:{2, 2, 100}。
- (2, 2) -> 4。森林:{4, 100}。
- (4, 100) -> 104。
- 权值为 100 的叶结点在最后一步才参与合并,直接作为根结点的孩子,因此其深度为 1。
@@ -0,0 +1,107 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.5 哈夫曼树和哈夫曼编码</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 基本概念与性质**
1. ( ) 哈夫曼树的构造过程每次选择()进行合并。
A. 权值最小的两个根结点 B. 权值最大的两个根结点
C. 深度最大的两个结点 D. 编号最小的两个结点
2. ( ) 哈夫曼编码最重要的结构性质是?
A. 编码长度必须为偶数
B. 任意一个字符的编码都不是另一个字符编码的前缀
C. 所有字符编码长度相同
D. 高频字符编码一定以 `0` 开头
3. ( ) 若哈夫曼树有 $n$ 个叶结点,则总结点数为?
A. $2n$ B. $n^2$ C. $2n - 1$ D. $n + 1$
4. 含 8 个叶结点的哈夫曼树有 \_\_\_\_\_\_\_\_ 个非叶结点。
5. ( ) 在字符频率不相等的情况下,通常频率越高的字符,其哈夫曼编码?
A. 越短或不长于低频字符 B. 一定越长
C. 长度完全随机 D. 一定与频率相等
6. ( ) 哈夫曼树的带权路径长度 `WPL` 定义为?
A. 所有内部结点权值的平方和
B. 所有叶结点的权值乘以其到根的边数后求和
C. 所有结点权值之和
D. 所有叶结点深度之和
---
### **题型二: 构造过程与带权路径长度**
7. ( ) 用权值 5, 7, 10, 15 构造哈夫曼树,其带权路径长度为?
A. 76 B. 74 C. 71 D. 66
8. ( ) 用权值 2, 3, 7, 9, 18 构造哈夫曼树,其带权路径长度为?
A. 75 B. 79 C. 78 D. 77
9. ( ) 用权值 4, 6, 8, 12, 20 构造哈夫曼树,其带权路径长度为?
A. 108 B. 104 C. 112 D. 100
10. ( ) 权值为 4, 6, 9, 13,哈夫曼算法第一次合并后,新产生的权值是?
A. 15 B. 17 C. 22 D. 10
---
### **题型三: 编码长度与压缩率**
11. ( ) 字符权值依次为 5, 9, 12, 13, 16, 45。按哈夫曼算法构造后,权值最大的字符编码长度为?
A. 5 B. 1 C. 2 D. 4
12. ( ) 字符权值依次为 2, 3, 5, 10。按哈夫曼算法构造后,权值最大的字符编码长度为?
A. 2 B. 3 C. 0 D. 1
13. ( ) 字符权值依次为 1, 2, 4, 8, 16。按哈夫曼算法构造后,权值最大的字符编码长度为?
A. 4 B. 1 C. 2 D. 0
14. 权值为 3, 4, 6, 8, 12, 20 时,哈夫曼编码的加权平均码长为 \_\_\_\_\_\_\_\_\_\_\_\_(加权平均码长 = 带权路径长度 / 总权值之和)。
15. 权值为 2, 3, 5, 10 时,哈夫曼编码的加权平均码长为 \_\_\_\_\_\_\_\_\_\_\_\_。
16. 权值为 5, 9, 12, 13, 16, 45 时,哈夫曼编码的加权平均码长为 \_\_\_\_\_\_\_\_\_\_\_\_。
17. 权值为 4, 7, 10, 15, 19 时,哈夫曼编码的加权平均码长为 \_\_\_\_\_\_\_\_\_\_\_\_。
---
### **题型四: 前缀码与解码**
18. ( ) 编码集合 `{0, 10, 110, 111}`?
A. 不是前缀码 B. 所有码字长度必须相同
C. 无法判断 D. 是前缀码
19. ( ) 编码集合 `{0, 01, 10, 11}`?
A. 不是前缀码 B. 可以唯一解码但不是前缀码
C. 所有码字长度必须相同 D. 无法判断
20. ( ) 编码集合 `{00, 01, 10, 110}`?
A. 无法判断 B. 是前缀码
C. 不是前缀码 D. 所有码字长度必须相同
21. ( ) 编码集合 `{1, 00, 010, 011}`?
A. 所有码字长度必须相同 B. 无法判断
C. 是前缀码 D. 不是前缀码
22. ( ) 设编码 `A → 0`, `B → 10`, `C → 110`, `D → 111`。比特串 `0101110` 解码结果为?
A. ADBC B. ABDA C. ACBD D. ABCD
23. 设编码 `A → 00`, `B → 01`, `C → 1`,字符串 `ABCA` 编码后的比特串为 ____________。
---
### **题型五: 综合应用**
24. ( ) 某文件只含四种字符,出现次数分别为 40, 30, 20, 10。若使用定长编码,每个字符需 2 位;使用最优哈夫曼编码后,总比特数为?
A. 200 B. 180 C. 160 D. 190
25. ( ) 若 $n$ 个字符的权值完全相同,且 $n = 8$,则最优二进制前缀编码中每个字符的码长为?
A. 3 B. 2 C. 4 D. 不一定相同
26. ( ) 权值集合为 1, 1, 1, 1, 100。哈夫曼树中权值 100 的叶结点深度为?
A. 4 B. 1 C. 2 D. 3
@@ -0,0 +1,103 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.6 各种排序算法</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | D | A | B | D | A | B | C |
| **题号** | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| **答案** | A | C | D | A | C | A | B | A | B | 6 |
| **题号** | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| **答案** | B | 1 | B | C | 4 | B | C | D | C | D |
| **题号** | 31 | 32 | 33 | 34 |
| **答案** | $O(n+k)$ | C | A | B |
---
### 详细解析
#### 题型一:排序性质与复杂度
1. **答案:A**
稳定排序不会改变关键字相等元素的原始相对次序。归并排序在合并两个有序段时,若遇到相等元素,优先取左边段的元素即可保持稳定。快速排序、堆排序和简单选择排序的标准实现通常是不稳定的。
2. **答案:B**
归并排序通过递归将数组分成两半,总共需要递归 $\log_2 n$ 层,每一层合并的总时间复杂度为 $O(n)$。因此,其最坏时间复杂度为 $O(n \log n)$。简单选择排序、冒泡排序和直接插入排序的最坏情况均为 $O(n^2)$。
3. **答案:C**
对于已经有序的数组,带提前终止标记的冒泡排序在第一趟扫描时,不会发生任何元素交换。此时,终止标记会触发算法立即结束。因此,只需要进行一趟($n-1$ 次)相邻元素的比较,最好时间复杂度为 $O(n)$。
4. **答案:D**
直接插入排序的性能与数组中逆序对的数量密切相关。当数组接近有序时,逆序对极少,每个待插入的元素在向前比较时很快就能找到插入位置,向前移动的距离很短,因此排序速度很快。
5. **答案:A**
简单选择排序的比较次数与数组的初始状态无关。在第 $i$ 趟中,它需要在剩余未排序的 $n-i$ 个元素中进行 $n-i-1$ 次比较以寻找最小值。总的比较次数固定为 $\frac{n(n-1)}{2}$,因此其数量级为 $O(n^2)$。
6. **答案:B**
快速排序在理想情况和平均情况下,基准元素能将区间较为均衡地划分为两部分,递归深度约为 $\log_2 n$,每层的总工作量为 $O(n)$,因此平均时间复杂度为 $O(n \log n)$。
7. **答案:D**
计数排序是一种空间换时间的非比较排序算法。它需要根据数据范围创建一个计数数组,因此非常适合关键字为整数且数据范围(最大值与最小值的差)不大的情况。
8. **答案:A**
基数排序、计数排序和桶排序都属于非比较排序,它们利用元素的固有特征进行“分配”和“收集”,而不是通过元素间的两两比较来决定顺序。归并、快速和堆排序都是比较排序。
9. **答案:B**
归并排序是最坏情况下时间复杂度为 $O(n \log n)$ 且具有稳定性的排序算法。快速排序最坏是 $O(n^2)$ 且不稳定;堆排序是 $O(n \log n)$ 但不稳定;简单选择排序是 $O(n^2)$。
10. **答案:C**
每次交换相邻元素,最多只能消除一个逆序对。因此,要将数组排成升序(消除所有逆序对),所需的最少交换次数正好等于原数组中逆序对的总数。冒泡排序的交换次数即为此值。
11. **答案:A**
如果快速排序每次选取的基准恰好都是当前区间的最小(或最大)元素,那么划分将极度不均衡:一个子区间为空,另一个子区间包含其余所有元素。这会导致递归树退化成一条单链,递归深度达到 $O(n)$。
12. **答案:C**
这是比较排序的时间复杂度下界定理。对于 $n$ 个不同元素的排列,共有 $n!$ 种可能。任何比较排序的决策二叉树至少要有 $n!$ 个叶子结点,因此树的高度(即最坏比较次数)至少为 $\log_2(n!) = \Omega(n \log n)$。
13. **答案:D**
在 C++ STL 中,`stable_sort` 使用归并排序等稳定算法来实现,`stable` 一词表示该算法能够保证:对于所有关键字相等的元素,它们在排序后的相对前后顺序与排序前完全一致。
#### 题型二:基础排序过程模拟
14. **答案:A**
一趟冒泡排序从左到右依次比较并交换逆序的相邻元素:
- `[5, 1, 4, 2, 8]` -> `[1, 5, 4, 2, 8]` (5,1交换)
- `[1, 5, 4, 2, 8]` -> `[1, 4, 5, 2, 8]` (5,4交换)
- `[1, 4, 5, 2, 8]` -> `[1, 4, 2, 5, 8]` (5,2交换)
- `[1, 4, 2, 5, 8]` -> `[1, 4, 2, 5, 8]` (5,8不交换)
15. **答案:C**
- `[4, 1, 3, 2]` -> `[1, 4, 3, 2]` (4,1)
- `[1, 4, 3, 2]` -> `[1, 3, 4, 2]` (4,3)
- `[1, 3, 4, 2]` -> `[1, 3, 2, 4]` (4,2)
16. **答案:A**
简单选择排序的第一趟任务是在整个数组 `[5, 1, 4, 2, 8]` 中寻找最小元素。找到最小值 `1` 后,将其与首位置的 `5` 进行交换,结果为 `[1, 5, 4, 2, 8]`。
17. **答案:B**
在数组 `[3, 2, 1, 5, 4]` 中,最小元素为 `1`。将 `1` 与首位置的 `3` 交换,结果为 `[1, 2, 3, 5, 4]`。
18. **答案:A**
直接插入排序依次将元素插入已排序的前缀中。前 4 个元素为 `5, 2, 4, 6`,将它们排好序后,前缀变为 `[2, 4, 5, 6]`。后面的元素 `1, 3` 原封不动。结果为 `[2, 4, 5, 6, 1, 3]`。
19. **答案:B**
前 5 个元素为 `8, 3, 5, 1, 9`,将它们排好序后,前缀变为 `[1, 3, 5, 8, 9]`。最后一个元素 `2` 原封不动。结果为 `[1, 3, 5, 8, 9, 2]`。
20. **答案:6**
冒泡排序的元素交换总次数等于数组的逆序对数。数组 `[6, 1, 5, 2, 4]` 中,(6,1), (6,5), (6,2), (6,4), (5,2), (5,4) 为逆序对,共 6 个。
21. **答案:B**
数组 `[1, 2, 3, 4, 5]` 已经完全升序。在第一趟冒泡扫描过程中,不会发生任何交换。如果算法带有提前终止标记(如 `flag`),检测到无交换发生,就会判断数组已有序,直接结束排序。
22. **答案:1**
第一趟简单选择排序在 `[3, 1, 4, 2]` 中找到最小值 `1`,并与第一个位置的 `3` 交换。交换后数组变为 `[1, 3, 4, 2]`,首元素为 `1`。
#### 题型三:快速排序
23. **答案:B**
以末元素 `5` 为基准。遍历数组,将小于等于 `5` 的元素放到数组前面部分:
`4` <= 5 (保留), `2` <= 5 (保留), `7` > 5 (不管), `3` <= 5 (换到前面), `6` > 5 (不管), `1` <= 5 (换到前面)。
所有小于 5 的元素被移到前端:`[4, 2, 3, 1]`。然后将基准 `5` 换到它们后面。大于 5 的 `[7, 6]` 在最后。一种可能的结果为 `[4, 2, 3, 1, 5, 7, 6]`。
24. **答案:C**
以 `6` 为基准划分 `[9, 3, 7, 1, 8, 2, 6]`。小于等于 `6` 的元素 `[3, 1, 2]` 被移到前面,随后放置基准 `6`,大于 `6` 的元素 `[9, 7, 8]` 在后面。一种可能的结果为 `[3, 1, 2, 6, 8, 7, 9]`。
25. **答案:4**
如果每次都能恰好均分,递归树的每一层,子数组长度都会减半。从长度 16 开始,规模变化为:16 $\rightarrow$ 8 $\rightarrow$ 4 $\rightarrow$ 2 $\rightarrow$ 1。对于长度大于 1 的区间都需要进行划分,因此共产生 4 层非空划分(规模分别为 16, 8, 4, 2 的层)。
#### 题型四:逆序对、代码与综合应用
26. **答案:B**
在 `[3, 1, 2]` 中,满足“前面大于后面”的数对有:(3, 1) 和 (3, 2),共 2 个。
27. **答案:C**
数组 `[5, 4, 3, 2, 1]` 是完全逆序的,任意两个元素都构成一个逆序对。总数为 $\binom{5}{2} = \frac{5 \times 4}{2} = 10$ 个。
28. **答案:D**
在 `[2, 4, 1, 3, 5]` 中,逆序对有:(2, 1), (4, 1), (4, 3),共 3 个。
29. **答案:C**
只允许相邻元素交换时,最少交换次数等于逆序对数。数组 `[4, 1, 3, 2]` 的逆序对有:(4, 1), (4, 3), (4, 2), (3, 2),共 4 个。
30. **答案:D**
“相同关键字保持原相对顺序”正是排序算法“稳定性”的定义。对于多关键字排序或含大量重复记录的情况,稳定性非常关键。
31. **答案:$O(n+k)$**
计数排序分为两步:第一步扫描 $n$ 个输入元素,在大小为 $k$ 的计数数组中累加频率,耗时 $O(n)$;第二步扫描计数数组生成输出,耗时 $O(k)$。总时间复杂度为 $O(n+k)$。
32. **答案:C**
如果快速排序固定选择第一个元素作为基准,而输入数组已经是升序的,那么每次基准都是当前区间的最小值。这导致划分极不均衡(左边 0 个元素,右边 $n-1$ 个元素),算法退化为 $O(n^2)$。
33. **答案:A**
一个算法在最坏情况下进行 $k=8$ 次比较,其决策树最多有 $2^8 = 256$ 个叶子结点。要保证正确排序 $n$ 个互异元素,必须满足 $n! \le 2^k$。$5! = 120 \le 256$,但 $6! = 720 > 256$。因此最多只能保证排序 5 个元素。
34. **答案:B**
多关键字排序中先按次要关键字(第二关键字)排序,再按主要关键字(第一关键字)进行**稳定排序**。在第二步中,第一关键字相同的元素,其相对顺序不会改变,从而保留了第一步按第二关键字排好的顺序。最终得到的是以第一关键字为主、第二关键字为次的正确字典序。
@@ -0,0 +1,139 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.6 各种排序算法</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 排序性质与复杂度**
1. ( ) 下列排序算法中,通常是稳定排序的是?
A. 归并排序 B. 快速排序
C. 堆排序 D. 简单选择排序
2. ( ) 下列排序算法中,最坏时间复杂度为 $O(n \log n)$ 的是?
A. 简单选择排序 B. 归并排序
C. 冒泡排序 D. 直接插入排序
3. ( ) 对已经有序的数组,带提前终止标记的冒泡排序最好时间复杂度为?
A. $O(n \log n)$ B. $O(n^2)$
C. $O(n)$ D. $O(1)$
4. ( ) 直接插入排序在数组接近有序时通常较快,原因是?
A. 它完全不需要比较
B. 它总能二分定位后不移动元素
C. 它只处理偶数下标
D. 每个元素向前移动的距离较短
5. ( ) 简单选择排序无论输入是否有序,比较次数的数量级通常是?
A. $O(n^2)$ B. $O(n)$
C. $O(\log n)$ D. $O(n \log n)$
6. ( ) 快速排序平均时间复杂度为?
A. $O(\log n)$ B. $O(n \log n)$
C. $O(n)$ D. $O(n^2)$
7. ( ) 计数排序适合的数据条件是?
A. 关键字是任意长字符串 B. 数据必须完全逆序
C. 只能有两个元素 D. 关键字为范围不大的整数
8. ( ) 下列排序中通常不基于元素间比较的是?
A. 基数排序 B. 归并排序
C. 快速排序 D. 堆排序
9. ( ) 若要求在最坏情况下保证 $O(n \log n)$ 且稳定,优先选择?
A. 简单选择排序 B. 归并排序
C. 快速排序 D. 堆排序
10. ( ) 若只允许相邻元素交换,把数组排成升序所需的最少交换次数等于?
A. 最大元素值 B. 不同元素个数
C. 数组的逆序对数 D. 数组长度
11. ( ) 快速排序在每次都选到当前区间最小元素作为基准时,递归深度可能达到?
A. $O(n)$ B. $O(1)$
C. $O(\log n)$ D. $O(\sqrt{n})$
12. ( ) 对 $n$ 个互不相同的元素,任何基于比较的排序算法在最坏情况下至少需要()次数量级的比较。
A. $\Omega(\log n)$ B. $\Omega(n^2)$
C. $\Omega(n \log n)$ D. $\Omega(n)$
13. ( ) 标准库 `stable_sort` 名称中的 `stable` 表示?
A. 结果一定严格递增 B. 算法不会使用额外空间
C. 运行时间恒为线性 D. 保持相等元素的相对次序
---
### **题型二: 基础排序过程模拟**
14. ( ) 对数组 `[5, 1, 4, 2, 8]` 进行一趟从左到右的冒泡操作(相邻逆序即交换),结果为?
A. `[1, 4, 2, 5, 8]` B. `[1, 2, 4, 5, 8]`
C. `[8, 2, 4, 1, 5]` D. `[1, 4, 2, 8, 5]`
17. ( ) 对数组 `[4, 1, 3, 2]` 进行一趟从左到右的冒泡操作(相邻逆序即交换),结果为?
A. `[1, 2, 3, 4]` B. `[2, 3, 1, 4]`
C. `[1, 3, 2, 4]` D. `[4, 2, 3, 1]`
18. ( ) 对数组 `[5, 1, 4, 2, 8]` 进行升序简单选择排序的第一趟,结果为?
A. `[1, 5, 4, 2, 8]` B. `[1, 2, 4, 5, 8]`
C. `[5, 1, 4, 2, 8]` D. `[8, 2, 4, 1, 5]`
19. ( ) 对数组 `[3, 2, 1, 5, 4]` 进行升序简单选择排序的第一趟,结果为?
A. `[4, 5, 1, 2, 3]` B. `[1, 2, 3, 5, 4]`
C. `[1, 2, 3, 4, 5]` D. `[3, 2, 1, 5, 4]`
22. ( ) 对数组 `[5, 2, 4, 6, 1, 3]` 进行直接插入排序,完成前 4 个元素的排序后,数组为?
A. `[2, 4, 5, 6, 1, 3]` B. `[1, 2, 3, 4, 5, 6]`
C. `[5, 2, 4, 6, 1, 3]` D. `[3, 1, 6, 5, 4, 2]`
23. ( ) 对数组 `[8, 3, 5, 1, 9, 2]` 进行直接插入排序,完成前 5 个元素的排序后,数组为?
A. `[2, 9, 8, 5, 3, 1]` B. `[1, 3, 5, 8, 9, 2]`
C. `[1, 2, 3, 5, 8, 9]` D. `[8, 3, 5, 1, 9, 2]`
20. 对数组 `[6, 1, 5, 2, 4]` 进行升序冒泡排序,元素交换总次数为\_\_\_\_\_\_\_\_\_\_。
27. ( ) 对数组 `[1, 2, 3, 4, 5]` 使用带提前终止标记的冒泡排序,第一趟结束后将?
A. 进入快速排序 B. 直接结束排序
C. 继续执行四趟 D. 把 1 与 5 交换
29. 对数组 `[3, 1, 4, 2]` 进行升序简单选择排序,第一趟交换后首元素为\_\_\_\_\_\_\_\_\_\_。
---
### **题型三:快速排序**
23. ( ) 使用快速排序,以末元素 5 为基准,对 `[4, 2, 7, 3, 6, 1, 5]` 划分一次,划分后数组为?
A. `[6, 7, 5, 1, 3, 2, 4]` B. `[4, 2, 3, 1, 5, 7, 6]`
C. `[1, 2, 3, 4, 5, 6, 7]` D. `[4, 2, 7, 3, 6, 1, 5]`
24. ( ) 使用快速排序,以末元素 6 为基准,对 `[9, 3, 7, 1, 8, 2, 6]` 划分一次,划分后数组为?
A. `[9, 3, 7, 1, 8, 2, 6]` B. `[9, 7, 8, 6, 2, 1, 3]`
C. `[3, 1, 2, 6, 8, 7, 9]` D. `[1, 2, 3, 6, 7, 8, 9]`
25. 快速排序对长度为 16 的数组每次都恰好均分,递归树的非空划分层数为 \_\_\_\_\_\_\_\_\_\_。
---
### **题型四:逆序对、代码与综合应用**
26. ( ) 数组 `[3, 1, 2]` 的逆序对数为?
A. 3 B. 2 C. 1 D. 4
27. ( ) 数组 `[5, 4, 3, 2, 1]` 的逆序对数为?
A. 11 B. 5 C. 10 D. 9
28. ( ) 数组 `[2, 4, 1, 3, 5]` 的逆序对数为?
A. 2 B. 4 C. 5 D. 3
29. ( ) 若只允许交换相邻元素,将 `[4, 1, 3, 2]` 变成升序序列,最少交换次数为?
A. 3 B. 6 C. 4 D. 2
30. ( ) 对含大量重复关键字的记录排序,并要求相同关键字保持原相对顺序,最关键的要求是算法具有?
A. 随机性 B. 递归性
C. 原地性 D. 稳定性
31. 用计数排序处理 $n$ 个值域为 $0 \sim k$ 的整数,时间复杂度为 \_\_\_\_\_\_\_\_\_\_。
32. ( ) 以下情形最容易使“首元素为基准”的快速排序退化到最坏情况的是?
A. 每次基准接近中位数 B. 数组长度是 2 的幂
C. 输入数组已经升序 D. 输入随机且元素互异
33. ( ) 若比较排序算法在最坏情况下只进行 8 次二元比较,它最多能保证正确排序多少个互不相同的元素?
A. 5 B. 4 C. 6 D. 8
34. ( ) 某稳定排序算法把记录按第二关键字稳定排序,再按第一关键字稳定排序,最终得到的是?
A. 只按第二关键字排序
B. 以第一关键字为主、第二关键字为次的字典序
C. 以第二关键字为主、第一关键字为次
D. 两个关键字都无序
@@ -0,0 +1,107 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.7 图论基本算法 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | D | A | B | C | D | 24 | B |
| 题号 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | C | 30 | A | B | C | D | 24 | B | B | A |
| 题号 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | A | B | C | D | A | B | 1 | D |
---
### 详细解析
#### **第一部分:图的基本概念与存储**
1. **答案:A**
一个有 $n$ 个顶点的无向图中,要形成一条边需要从 $n$ 个顶点中任选两个。因此,边的数量上限为组合数 $\binom{n}{2} = \frac{n(n-1)}{2}$。
2. **答案:B**
在一个有 $n$ 个顶点的有向图中,对于任意两个不同的顶点 $u$ 和 $v$,有向边 $(u, v)$ 和 $(v, u)$ 是两条不同的边。因此,每个顶点都可以作为起点,连接到其余 $n-1$ 个顶点,总边数最多为 $n(n-1)$。
3. **答案:C**
这被称为“握手定理”。在无向图中,每条边连接两个顶点,因此它为这两个端点各贡献 1 个度数。将所有顶点的度数相加,相当于每条边的贡献被计算了两次,因此总度数等于边数的两倍 ($2m$)。
4. **答案:D**
在有向图中,每条有向边 $(u, v)$ 只有一个起点和一个终点。它只对终点 $v$ 的入度贡献 1。因此,将所有顶点的入度相加,其总和等于图中的边数 $m$。同理,所有顶点的出度之和也等于边数 $m$。
5. **答案:A**
稠密图是指边数 $m$ 接近于顶点数平方 $n^2$ 的图。邻接矩阵使用 $O(n^2)$ 的空间来存储图,无论边数多少。对于稠密图,邻接矩阵的空间利用率较高,并且能以 $O(1)$ 的时间复杂度快速判断任意两点间是否存在边。
6. **答案:B**
稀疏图是指边数 $m$ 远小于 $n^2$ 的图(通常 $m$ 与 $n$ 是一个数量级)。邻接表只存储实际存在的边,其空间复杂度为 $O(n+m)$。对于稀疏图,使用邻接表比邻接矩阵能节省大量存储空间。
7. **答案:C**
邻接矩阵是一个 $n \times n$ 的二维数组,其中 $n$ 是顶点数。因此,它需要 $n^2$ 个存储单元,空间复杂度为 $O(n^2)$。
8. **答案:D**
在无向图中,边 $u - v$ 需要同时出现在 $u$ 的邻接表和 $v$ 的邻接表中。因此,每条边对应两个边结点,总共需要记录 $2m$ 次。
9. **答案:24**
根据无向图的握手定理,所有顶点度数之和等于边数的两倍。因此,总度数为 $2 \times 12 = 24$。
10. **答案:B**
在有向图中,所有顶点的出度之和等于图的总边数。因此,总出度为 20。
11. **答案:C**
完全无向图包含任意两点间的一条边。边数为 $\binom{8}{2} = \frac{8 \times 7}{2} = 28$。
12. **答案:30**
在一个有 6 个顶点的完全有向图中,每个顶点都可以向其余 5 个顶点连出一条边。总边数为 $6 \times 5 = 30$。
13. **答案:A**
由于所有顶点的度数之和($2m$)是一个偶数,而偶数度顶点的度数之和也必为偶数,因此奇数度顶点的度数之和必须是偶数。这只有在奇数度顶点的个数为偶数时才成立。
14. **答案:B**
邻接矩阵使用二维数组 `A[u][v]` 来存储边信息。判断边是否存在只需一次数组访问,这是常数时间操作,即 $O(1)$。
15. **答案:C**
在无序邻接表中,要判断边 `(u, v)` 是否存在,需要遍历顶点 $u$ 的邻接链表,检查其中是否包含顶点 $v$。最坏情况下需要扫描完 $u$ 的所有邻接点。
16. **答案:D**
树的充要条件之一是“连通且边数为 $n - 1$”。仅有 $n-1$ 条边并不能保证图是连通的(例如,一个有 $n-1$ 个顶点的连通图外加一个孤立点)。因此,它不一定是树。
17. **答案:24**
树是连通的无环图,其边数恒为顶点数减一。对于有 25 个顶点的树,其边数为 $25 - 1 = 24$。
18. **答案:B**
一棵树保留了原图的所有 $n$ 个顶点,且恰好有 $n - 1$ 条边。因此,需要从原有的 $m$ 条边中删除 $m - (n - 1) = m - n + 1$ 条边。
---
#### **第二部分:有向图、拓扑排序与强连通**
19. **答案:B**
Kahn 算法过程(每次选最小编号):
1. 初始零入度顶点:{1}。输出 1。
2. 移除 1 后,新增零入度顶点:{2, 3}。选 2。输出 2。
3. 移除 2 后,无新增。选 3。输出 3。
4. 移除 3 后,4 的入度变为 0。新增:{4}。输出 4。
5. 移除 4 后,5 的入度变为 0。新增:{5}。输出 5。
序列为 `[1, 2, 3, 4, 5]`。
20. **答案:A**
Kahn 算法过程:
1. 初始零入度顶点:{1, 2}。选 1。输出 1。
2. 移除 1 后,无新增。选 2。输出 2。
3. 移除 2 后,新增:{3, 4}。选 3。输出 3。
4. 移除 3 后,无新增。选 4。输出 4。
5. 移除 4 后,5 的入度变为 0。新增:{5}。输出 5。
6. 移除 5 后,6 的入度变为 0。新增:{6}。输出 6。
序列为 `[1, 2, 3, 4, 5, 6]`。
21. **答案:B**
Kahn 算法过程:
1. 初始:{1}。输出 1。
2. 新增:{2, 4}。选 2。输出 2。
3. 新增:{3}。选 3。输出 3。
4. 无新增。选 4。输出 4。
5. 新增:{5}。选 5。输出 5。
6. 6 的入度变为 0。新增:{6}。输出 6。
7. 7 的入度变为 0。新增:{7}。输出 7。
序列为 `[1, 2, 3, 4, 5, 6, 7]`。
22. **答案:A**
拓扑排序是对有向图中顶点的一种线性排序,要求对于每一条有向边 $(u, v)$,顶点 $u$ 都出现在 $v$ 之前。这种排序存在的充要条件是图中没有有向环。
23. **答案:B**
Kahn 算法通过不断移除入度为 0 的顶点来工作。如果在所有零入度顶点都被移除后,图中仍有顶点剩余,那么这些剩余的顶点必定相互依赖,形成一个或多个有向环。
24. **答案:C**
如果在某一步可以选择的零入度顶点多于一个,那么这些顶点在当前拓扑序列中的相对顺序是不固定的。选择不同的顶点将导致最终的拓扑序列不同,因此拓扑序可能不唯一。
25. **答案:D**
强连通分量是图中的一个极大子图,而强连通分量要求其中任意两个顶点 $u, v$ 都是双向可达的,即存在从 $u$ 到 $v$ 的路径,也存在从 $v$ 到 $u$ 的路径。
26. **答案:A**
将每个强连通分量(SCC)视为一个单一的“节点”,并在它们之间根据原始图的边添加新的有向边,所形成的图称为缩点图。如果缩点图中存在一个环,那么这个环上的所有“节点”实际上是相互可达的,它们本应属于同一个强连通分量,这与定义矛盾。因此,缩点图必然是无环的。
27. **答案:B**
Tarjan 算法和 Kosaraju 算法是两种经典的用于在线性时间内求解有向图强连通分量的算法。Prim 和 Kruskal 算法用于求解最小生成树。
28. **答案:1**
若在 Kahn 算法的每一步中,可选的零入度顶点都只有一个,那么顶点的输出顺序是唯一确定的,从而使得整个图的拓扑序列唯一。
29. **答案:D**
在有向无环图(DAG)上进行动态规划时,很多状态的计算依赖于其前驱结点的状态。拓扑排序提供了一个线性的顶点序列,保证了在计算任何一个顶点的状态时,它的所有前驱结点的状态都已经计算完毕。
@@ -0,0 +1,109 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.7 图论基本算法</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_
---
### **第一部分:图的基本概念与存储**
1. ( ) 一个有 $n$ 个顶点、无自环和重边的无向图,最多有多少条边?
A. $\frac{n(n - 1)}{2}$ B. $n(n - 1)$ C. $n^2$ D. $n - 1$
2. ( ) 一个有 $n$ 个顶点、无自环和重边的有向图,最多有多少条边?
A. $n - 1$ B. $n(n - 1)$ C. $\frac{n(n - 1)}{2}$ D. $n^2$
3. ( ) 无向图中所有顶点度数之和等于()。
A. 顶点数 B. 顶点数的两倍 C. 边数的两倍 D. 边数
4. ( ) 有向图中所有顶点入度之和等于()。
A. 顶点数 B. 边数的两倍 C. 出度最大值 D. 边数
5. ( ) 稠密图通常更适合使用()存储。
A. 邻接矩阵 B. 邻接表 C. 栈 D. 并查集
6. ( ) 稀疏图通常更适合使用()存储。
A. 栈 B. 邻接表 C. 邻接矩阵 D. 二维前缀和
7. ( ) 用邻接矩阵表示一个含 $n$ 个顶点的图,空间复杂度为()。
A. $O(m^2)$ B. $O(n)$ C. $O(n^2)$ D. $O(n + m)$
8. ( ) 用邻接表表示无向图时,若图有 $m$ 条边,边结点通常记录()次。
A. $m$ B. $n + m$ C. $m^2$ D. $2m$
9. 一个无向图有 12 条边,则所有顶点度数之和为\_\_\_\_\_\_\_\_。
10. ( ) 一个有向图有 20 条边,则所有顶点出度之和为()。
A. 无法确定 B. 20 C. 10 D. 40
11. ( ) 一个有 8 个顶点的完全无向图有()条边。
A. 32 B. 56 C. 28 D. 16
12. 一个有 6 个顶点的完全有向图(无自环)共有 \_\_\_\_\_\_\_\_ 条边。
13. ( ) 无向图中奇数度顶点的个数一定是()。
A. 偶数 B. 奇数 C. 不超过 2 D. 等于边数
14. ( ) 在邻接矩阵中判断边 `(u, v)` 是否存在,时间复杂度通常为()。
A. $O(n + m)$ B. $O(1)$ C. $O(n)$ D. $O(m)$
15. ( ) 在无序邻接表中判断边 `(u, v)` 是否存在,最坏需要扫描()。
A. 全部顶点的邻接矩阵 B. 只看顶点编号
C. $u$ 的全部邻接点 D. 固定一个元素
16. ( ) 若无向图有 $n$ 个顶点且恰有 $n - 1$ 条边,则它()。
A. 一定是树 B. 一定有环
C. 一定不连通 D. 不一定是树,还需要连通
17. 一棵有 25 个顶点的树有\_\_\_\_\_\_\_\_条边。
18. ( ) 一个无向连通图有 $n$ 个顶点、$m$ 条边,要删去最少多少条边才能得到一棵树?
A. $m + 1$ B. $m - n + 1$ C. $m - n$ D. $n - 1$
---
### **第二部分:有向图、拓扑排序与强连通**
19. ( ) 有向无环图顶点为 $1 \sim 5$,边集为 `[(1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]`。每次选择编号最小的零入度顶点,所得拓扑序为()。
A. `[5, 4, 3, 2, 1]` B. `[1, 2, 3, 4, 5]`
C. `[5, 1, 2, 3, 4]` D. `[2, 3, 4, 5, 1]`
20. ( ) 有向无环图顶点为 $1 \sim 6$,边集为 `[(1, 3), (2, 3), (2, 4), (3, 5), (4, 5), (5, 6)]`。每次选择编号最小的零入度顶点,所得拓扑序为()。
A. `[1, 2, 3, 4, 5, 6]` B. `[6, 5, 4, 3, 2, 1]`
C. `[2, 3, 4, 5, 6, 1]` D. `[6, 1, 2, 3, 4, 5]`
21. ( ) 有向无环图顶点为 $1 \sim 7$,边集为 `[(1, 2), (1, 4), (2, 3), (4, 5), (3, 6), (5, 6), (6, 7)]`。每次选择编号最小的零入度顶点,所得拓扑序为()。
A. `[7, 6, 5, 4, 3, 2, 1]` B. `[1, 2, 3, 4, 5, 6, 7]`
C. `[7, 1, 2, 3, 4, 5, 6]` D. `[2, 3, 4, 5, 6, 7, 1]`
22. ( ) 一个有向图存在拓扑排序,当且仅当它()。
A. 没有有向环 B. 强连通
C. 每个顶点出度相同 D. 边数为 $n - 1$
23. ( ) 使用 Kahn 算法进行拓扑排序时,若最终输出顶点数少于 $n$,说明图中()。
A. 所有顶点入度为零 B. 存在有向环
C. 不存在边 D. 一定是树
24. ( ) 若一个 DAG(有向无环图)在某一步同时存在两个零入度顶点,则拓扑序()。
A. 一定不存在 B. 一定有环
C. 可能不唯一 D. 一定唯一
25. ( ) 有向图中两个顶点 $u, v$ 属于同一强连通分量(强连通分量是指图中的一个极大子图使得这个子图中任意两个顶点 $u, v$ 都是双向可达的),意味着()。
A. 二者之间必须有直接边 B. 二者入度相等
C. 二者编号相邻 D. $u$ 可达 $v$ 且 $v$ 可达 $u$
26. ( ) 把有向图的每个强连通分量缩成一个点后,得到的图一定是()。
A. 有向无环图 B. 完全图
C. 无向树 D. 二分图
27. ( ) 求有向图强连通分量可使用()。
A. 二分查找 B. Tarjan 算法
C. Prim 算法 D. Kruskal 算法
28. 一个 DAG 有 $n$ 个顶点。若其拓扑序唯一,则 Kahn 算法每一步可选的零入度顶点数必须为 \_\_\_\_\_\_\_\_。
29. ( ) 在 DAG 上按拓扑序进行动态规划的关键原因是()。
A. DAG 的边权一定为正
B. 拓扑序按编号递增
C. DAG 一定是树
D. 处理一个顶点时,它的所有前驱都已处理
@@ -0,0 +1,113 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.8 hash 表和二叉搜索树 答案</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :------: | :--: | :--: | :--: | :----: | :--: | :--: | :--: | :--: | :--: | :--: |
| **答案** | A | B | C | B | A | B | C | D | B | 1 |
| **题号** | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| **答案** | B | 8 | D | $O(n)$ | D | A | B | C | D | A |
| **题号** | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| **答案** | B | C | D | B | D | 4 | 4 | D | D | 4 |
---
### 详细解析
#### 题型一:散列表基本概念
1. **答案:A**
散列表(Hash Table)的核心思想是通过散列函数将数据的关键字映射到表中的一个存储位置,从而实现在理想情况下的常数时间 $O(1)$ 的直接访问。
2. **答案:B**
当不同的关键字经过散列函数计算得到相同的散列地址时,这种现象被称为冲突或碰撞。解决冲突是散列表设计的核心问题之一。
3. **答案:C**
装载因子 $\alpha$ 定义为散列表中已经存储的元素数量除以散列表的容量(表长)。它反映了散列表的拥挤程度,是决定是否需要扩容的重要指标。
4. **答案:B**
**【概念详析:开放地址法】** 开放地址法不使用任何附加的数据结构(如链表)。当准备插入一个元素发生冲突时,它会使用某种预先设定的**探测序列**(例如线性探查 $i+1, i+2$;二次探查 $i+1^2, i-1^2$ 等),在散列表内部向后寻找下一个**空的槽位**并将元素放入。
5. **答案:A**
**【概念详析:拉链法】** 拉链法(链地址法)是解决冲突最常用的方法。它的做法是在散列表的每一个槽位上外挂一个链表(或动态数组)。当多个元素被散列到同一个槽位时,就将它们直接追加到这个槽位对应的链表中。
6. **答案:B**
如果散列函数均匀且冲突较少,散列表的平均查找时间复杂度接近 $O(1)$。
7. **答案:C**
**【概念详析:一次聚集】** 这是**开放地址法**中“线性探查”特有的缺点。当发生冲突并向后寻找空槽位时,多个不同的探测序列容易在某一块区域发生重叠合并。这导致数组中出现越来越长的一段“被连续占用”的区域(即一次聚集)。之后散列到这片区域及其附近的元素,都需要进行大量的线性探测才能找到空位,从而导致性能严重退化。
8. **答案:D**
为了最大程度地降低散列表的冲突率,设计或选择一个好的散列函数至关重要。一个好的散列函数应该能够快速计算,并且能够将关键字尽可能均匀、随机地映射到散列表的各个槽位上。
#### 题型二:散列表插入与拉链法模拟
9. **答案:B**
散列函数 $h(x) = x \bmod 11$。
- $h(18) = 7$。槽位 7 链表:`[18]`。
- $h(35) = 2$。槽位 2 链表:`[35]`。
- $h(68) = 2$。发生冲突,追加到槽位 2 的链表后。槽位 2 链表变为:`[35, 68]`。
此时,槽位 2 的链表长度为 2。
10. **答案:1**
根据上题的完整插入过程:
- `h(18)=7`, `h(26)=4`, `h(35)=2`, `h(9)=9`, `h(68)=2`, `h(74)=8`。
- 槽位 2 链表:`[35, 68]`(长度 2)。
- 其他非空槽位 4, 7, 8, 9 的链表长度均为 1。
- 因此,只有一个槽位(槽位 2)的链表长度大于 1。
11. **答案:B**
散列函数 $h(x) = x \bmod 10$。
- $h(21) = 1$, $h(31) = 1$。槽位 1 的链表为 `[21, 31]`,长度为 2。
- $h(42) = 2$, $h(12) = 2$, $h(52) = 2$。槽位 2 的链表为 `[42, 12, 52]`,长度为 3。
最长的链表在槽位 2,其长度为 3。
12. **答案:8**
大小为 10 的散列表中,只有槽位 1 和槽位 2 被使用。剩余的槽位(0, 3, 4, 5, 6, 7, 8, 9)均为空,共 8 个空槽位。
13. **答案:D**
所有数字除以 13 的余数:
$5 \bmod 13 = 5$, $18 \bmod 13 = 5$, $31 \bmod 13 = 5$, $44 \bmod 13 = 5$, $57 \bmod 13 = 5$。
这 5 个元素全部被散列到了槽位 5 中,因此链表包含 5 个元素。
14. **答案:$O(n)$**
这是拉链法的最坏情况。当所有 $n$ 个元素都散列到同一个槽位时,散列表退化成了一条普通的单链表,此时查找任意元素都需要遍历链表,时间复杂度退化为 $O(n)$。
15. **答案:D**
$10 \bmod 7 = 3$; $17 \bmod 7 = 3$; $24 \bmod 7 = 3$; $31 \bmod 7 = 3$。这些元素在拉链法中都挂在了下标为 3 的链表上。
16. **答案:A**
装载因子 $\alpha = \frac{\text{已存元素数}}{\text{散列表大小}} = \frac{7}{10} = 0.7$。
#### 题型三:二叉搜索树基本性质
17. **答案:B**
二叉搜索树(BST)的核心性质:对于任意一个结点,其左子树中所有结点的关键字均小于该结点,右子树中所有结点的关键字均大于该结点。
18. **答案:C**
由于左子树 $<$ 根 $<$ 右子树,按照“左-根-右”的顺序进行中序遍历,必然得到一个严格递增的有序序列。
19. **答案:D**
根据 BST 的性质,如果目标关键字 $x$ 小于当前结点的值,那么它只可能存在于当前结点的左子树中,所以应该转向左子树继续查找。
20. **答案:A**
查找过程是从根结点出发的一条向下路径。最坏情况下的比较次数即为树的高度。如果树的高度很高(即严重不平衡),查找效率就会变低。
21. **答案:B**
每次插入比前面所有元素都大的值,新元素只能不断地作为前一个元素的右孩子,整棵树退化成了一条只有右孩子的单向链表,高度变为 $n$。
22. **答案:C**
平衡的二叉搜索树能够保证树的左右两边节点数大致相同,树的层数被压到了最低,其高度的渐进复杂度是 $O(\log n)$。
#### 题型四:二叉搜索树构造与遍历
23. **答案:D**
依次插入 `8, 3, 10, 1, 6, 14, 4, 7, 13`:
- 根为 8。
- 左子树包含 `<8` 的:3, 1, 6, 4, 7。
- 右子树包含 `>8` 的:10, 14, 13。
- 构建完成后,前序遍历(根-左-右)为 `[8, 3, 1, 6, 4, 7, 10, 14, 13]`。
24. **答案:B**
依次插入 `5, 2, 8, 1, 3, 7, 9`:
- 根为 5。
- 左子树:根为 2,左孩子 1,右孩子 3。
- 右子树:根为 8,左孩子 7,右孩子 9。
- 前序遍历(根-左-右)为 `[5, 2, 1, 3, 8, 7, 9]`。
25. **答案:D**
依次插入 `12, 6, 18, 3, 9, 15, 20, 8`:
- 根为 12。
- 左子树:根为 6,左孩子 3,右孩子 9(9 的左孩子是 8)。
- 右子树:根为 18,左孩子 15,右孩子 20。
- 前序遍历为 `[12, 6, 3, 9, 8, 18, 15, 20]`。
26. **答案:4**
由上题的树形结构:最深的路径是 `12 -> 6 -> 9 -> 8`,共 4 层,所以高度为 4。
27. **答案:4**
插入 `8, 3, 10, 1, 6, 14, 4, 7, 13` 后,最深的路径是 `8 -> 3 -> 6 -> 4` (或 `...->7`),共 4 层,所以高度为 4。
28. **答案:D**
根据前序遍历 `[8, 3, 1, 6, 4, 7, 10, ...]` 可以推断出树的结构:8 是根,3 是其左孩子,6 是 3 的右孩子,7 是 6 的右孩子。因此,关键字 7 的父结点是 6。
29. **答案:D**
当查找的关键字不存在时,算法会不断向下比较,直到走到叶子结点之后,遇到原本应该存在的那个方向的 `nullptr` 指针,此时搜索终止并宣告失败。
30. **答案:4**
要使一棵二叉搜索树高度最小,需要让其尽量平衡。方法是选择排序后序列的中位数作为根结点。对于序列 `1, 2, 3, 4, 5, 6, 7`,中位数是 4。以 4 为根可保证左右子树各有 3 个元素,得到最优的高度。
@@ -0,0 +1,114 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.8 hash 表和二叉搜索树</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 散列表基本概念**
1. ( ) 散列表的核心思想是?
A. 通过散列函数把关键字映射到存储位置 B. 把所有关键字完全排序
C. 只使用链表顺序查找 D. 把数据存成二叉树后遍历
2. ( ) 两个不同关键字被散列到同一位置,这种现象称为?
A. 稳定性 B. 冲突 C. 递归 D. 溢出
3. ( ) 装载因子 $\alpha$ 通常定义为?
A. 冲突次数除以元素数 B. 关键字最大值除以表长
C. 已存元素数除以表长 D. 表长除以元素数
4. ( ) 在散列表中,开放地址法解决冲突的基本思想是?
A. 将所有冲突的元素挂在同一个数组槽位的链表中
B. 当发生冲突时,按照某种探测序列在散列表内寻找下一个空的槽位
C. 建立一个公共的溢出区存放所有冲突元素
D. 动态扩大散列表的容量
5. ( ) 拉链法(链地址法)解决冲突时,每个表槽通常保存?
A. 一个链表或动态容器 B. 一个固定唯一关键字
C. 一棵最小生成树 D. 一张邻接矩阵
6. ( ) 理想情况下,散列表成功查找的平均时间复杂度接近?
A. $O(n^2)$ B. $O(1)$ C. $O(\log n)$ D. $O(n)$
7. ( ) 使用开放地址法中的“线性探查”解决冲突时,容易出现连续已占用区域不断扩大,导致查找时间激增的现象,这种现象称为?
A. 拓扑冲突 B. 尾递归 C. 一次聚集 D. 路径压缩
8. ( ) 为了降低散列表冲突,通常应选择?
A. 始终返回 0 的函数 B. 只取关键字最高位
C. 表长为 1 D. 分布较均匀且计算快速的散列函数
---
### **题型二: 散列表插入与拉链法模拟**
9. ( ) 大小为 11 的散列表采用哈希函数 $h(x) = x \bmod 11$ 和 **拉链法** 解决冲突,依次插入 18, 26, 35, 9, 68, 74。关键字 68 插入后,其所在槽位的链表长度为?
A. 1 B. 2 C. 3 D. 4
10. 在上述插入结束后,共有 \_\_\_\_\_\_\_\_\_\_\_\_ 个槽位的链表长度大于 1。
11. ( ) 大小为 10 的散列表采用哈希函数 $h(x) = x \bmod 10$ 和 **拉链法** 解决冲突,依次插入 21, 31, 42, 12, 52。插入结束后,最长的链表长度为?
A. 2 B. 3 C. 4 D. 5
12. 上述散列表中,空槽位(即链表长度为 0 的槽位)共有 \_\_\_\_\_\_\_\_\_\_\_\_ 个。
13. ( ) 大小为 13 的散列表采用 $h(x) = x \bmod 13$ 和 **拉链法** 解决冲突,依次插入 5, 18, 31, 44, 57。插入结束后,槽位 5 的链表中包含的元素个数为?
A. 2 B. 3 C. 4 D. 5
14. 在拉链法中,若所有 $n$ 个元素都散列到了同一个槽位,则查找任意一个元素的平均时间复杂度退化为 \_\_\_\_\_\_\_\_\_\_\_\_。
15. ( ) 大小为 7 的散列表采用 $h(x) = x \bmod 7$ 和 **拉链法** 解决冲突,依次插入 10, 17, 24, 31。这些元素最终都位于下标为()的槽位链表中?
A. 0 B. 5 C. 6 D. 3
16. ( ) 大小为 10 的散列表(不论采用拉链法还是开放地址法)已存 7 个元素,其装载因子为?
A. 0.7 B. 0.3 C. 7 D. 10/7
---
### **题型三: 二叉搜索树基本性质**
17. ( ) 二叉搜索树中,对任一结点,通常满足?
A. 每个结点恰有两个孩子
B. 左子树关键字小于该结点,右子树关键字大于该结点
C. 左子树关键字都更大
D. 左右子树必须等高
18. ( ) 对关键字互异的二叉搜索树进行中序遍历,得到的序列是?
A. 层序序列 B. 随机序列
C. 严格递增序列 D. 严格递减序列
19. ( ) 二叉搜索树查找关键字 $x$ 时,若 $x$ 小于当前结点关键字,应转向?
A. 右子树 B. 父结点 C. 任意叶结点 D. 左子树
20. ( ) 二叉搜索树的查找时间主要取决于?
A. 树的高度 B. 总结点权值
C. 叶结点编号 D. 边权是否相同
21. ( ) 若按严格递增顺序向空二叉搜索树插入 $1, 2, \dots, n$,树会退化为?
A. 只有左孩子的链 B. 只有右孩子的链
C. 完全二叉树 D. 满二叉树
22. ( ) 平衡二叉搜索树的理想高度数量级是?
A. $O(n)$ B. $O(n^2)$ C. $O(\log n)$ D. $O(1)$
---
### **题型四: 二叉搜索树构造与遍历**
23. ( ) 依次向空二叉搜索树插入 8, 3, 10, 1, 6, 14, 4, 7, 13,其前序遍历为?
A. `[1, 3, 4, 6, 7, 8, 10, 13, 14]` B. `[1, 4, 7, 6, 3, 13, 14, 10, 8]`
C. `[13, 7, 4, 14, 6, 1, 10, 3, 8]` D. `[8, 3, 1, 6, 4, 7, 10, 14, 13]`
24. ( ) 依次向空二叉搜索树插入 5, 2, 8, 1, 3, 7, 9,其前序遍历为?
A. `[9, 7, 3, 1, 8, 2, 5]` B. `[5, 2, 1, 3, 8, 7, 9]`
C. `[1, 2, 3, 5, 7, 8, 9]` D. `[1, 3, 2, 7, 9, 8, 5]`
25. ( ) 依次向空二叉搜索树插入 12, 6, 18, 3, 9, 15, 20, 8,其前序遍历为?
A. `[3, 6, 8, 9, 12, 15, 18, 20]` B. `[3, 8, 9, 6, 15, 20, 18, 12]`
C. `[8, 20, 15, 9, 3, 18, 6, 12]` D. `[12, 6, 3, 9, 8, 18, 15, 20]`
26. 依次插入 12, 6, 18, 3, 9, 15, 20, 8 构造二叉搜索树,其高度(根高度为 1)为 \_\_\_\_\_\_\_\_\_\_\_\_。
27. 依次插入 8, 3, 10, 1, 6, 14, 4, 7, 13 构造二叉搜索树,其高度(根高度为 1)为 \_\_\_\_\_\_\_\_\_\_\_\_。
28. ( ) 某二叉搜索树的前序遍历为 `[8, 3, 1, 6, 4, 7, 10, 14, 13]`,关键字 7 的父结点是?
A. 3 B. 8 C. 10 D. 6
29. ( ) 在二叉搜索树中查找不存在的关键字,搜索终止于?
A. 根结点 B. 任意叶结点后重新开始
C. 中序遍历末尾 D. 应继续查找方向上的空指针
30. 将数据 1, 2, 3, 4, 5, 6, 7 插入空二叉搜索树。若希望得到高度最小的树,根结点可选择 \_\_\_\_\_\_\_\_\_\_\_\_。
@@ -0,0 +1,145 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.9 原码、补码、反码</b></font></center>
### 答案速查
| 题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | A | B | C | D | A | 65536 | C | D | C | B |
| 题号 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | C | A | `10010101` | D | A | -74 | A | B | D | A |
| 题号 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **答案** | B | C | D | A | C | D | `11110000` | B | C | D |
---
### 详细解析
#### 题型一:表示范围与基本概念
1. **答案:A**
8 位无符号整数使用全部 8 个二进制位表示数值。其范围从 `00000000` (十进制 0) 到 `11111111` (十进制 $2^8 - 1 = 255$)。
2. **答案:B**
8 位有符号整数(补码)的范围是 $-2^{8-1}$ 到 $2^{8-1} - 1$,即 $-128$ 到 $127$。
3. **答案:C**
8 位原码的最高位是符号位,后 7 位是数值位。其范围从 `11111111` (十进制 $-(2^7-1)=-127$) 到 `01111111` (十进制 $2^7-1=127$)。
4. **答案:D**
- 原码:`00000000` (+0) 和 `10000000` (-0)。
- 反码:`00000000` (+0) 和 `11111111` (-0)。
- 补码:只有 `00000000` 表示 0,解决了“两个零”的问题。
5. **答案:A**
对于正整数,其原码、反码和补码的二进制表示是完全相同的。负数才需要进行变换。
6. **答案:65536**
16 位无符号整数可以表示从 0 到 $2^{16} - 1 = 65535$ 的所有整数。总共有 $65536$ 个不同的数值。
7. **答案:C**
16 位补码整数的范围是 $-2^{16-1}$ 到 $2^{16-1} - 1$,即 $-32768$ 到 $32767$。最小值是 $-32768$。
8. **答案:D**
在原码表示法中,最高位为 1 表示负数,其余位表示数值大小。`10000000` 的数值部分为 0,所以它表示 “负零”。
#### 题型二:原码、反码与补码转换
9. **答案:C**
$+37$ 是正数,其原码、反码、补码相同。$37 = 32 + 4 + 1 = 2^5 + 2^2 + 2^0$。其 8 位二进制表示为 `00100101`。
10. **答案:B**
求 $-37$ 的补码:
- 首先得到 $+37$ 的 8 位二进制:`00100101`。
- 按位取反(得到反码):`11011010`。
- 末位加 1(得到补码):`11011011`。
11. **答案:C**
求 $-64$ 的补码:
- $+64$ 的 8 位二进制:`01000000`。
- 按位取反:`10111111`。
- 末位加 1:`11000000`。
12. **答案:A**
求 $-18$ 的反码:
- $+18$ 的 8 位二进制:`00010010`。
- 按位取反:`11101101`。
13. **答案:`10010101`**
求 $-21$ 的原码:
- $+21$ 的 8 位二进制:`00010101`。
- 将符号位(最高位)变为 1:`10010101`。
14. **答案:D**
补码 `11110110` 是一个负数。求其十进制值:
- (方法一)减 1,再取反:`11110110` - 1 = `11110101`,取反为 `00001010`,即 10。所以原值为 $-10$。
- (方法二)连同符号位按位取反,再加 1:`11110110` 取反为 `00001001`,加 1 为 `00001010`,即 10。所以原值为 $-10$。
15. **答案:A**
补码 `10000001` 是一个负数。求其十进制值:
- 减 1,再取反:`10000001` - 1 = `10000000`,取反为 `01111111`,即 127。所以原值为 $-127$。
16. **答案:-74**
补码 `10110110` 是一个负数。求其十进制值:
- 减 1,再取反:`10110110` - 1 = `10110101`,取反为 `01001010`。
- `01001010` 转换为十进制是 $64 + 8 + 2 = 74$。所以原值为 $-74$。
#### 题型三:补码运算与溢出
17. **答案:A**
这道题考查基础的补码加法。
- $+45$ 的 8 位补码是 `00101101`。
- $-20$ 的 8 位补码求法:$+20$ 为 `00010100`,取反加一得到 `11101100`。
- 两者相加:`00101101 + 11101100 = (1)00011001`。
- 丢弃最高位溢出的进位 `1`,最终结果为 `00011001`(对应十进制的 25)。
18. **答案:B**
在计算机硬件(ALU)中,通常只设计加法器而没有专门的减法器。所有的减法运算 $A - B$ 都会被转化为加法运算 $A + (-B)$ 来执行。因此,$15 - 20$ 等价于计算 $15$ 的补码与 $-20$ 的补码之和。
19. **答案:D**
在补码表示法中,“连同符号位一起按位取反,然后再加一”是求一个数**相反数**的标准操作。即 `~x + 1` 等价于 $-x$。注意,这不一定等价于绝对值(当 $x$ 为正数时,$-x$ 是负数)。
20. **答案:A**
- $+10$ 为 `00001010`,故 $-10$ 的补码为 `11110110`。
- $+15$ 为 `00001111`,故 $-15$ 的补码为 `11110001`。
- 补码相加:`11110110 + 11110001 = (1)11100111`。
- 丢弃进位,结果位模式为 `11100111`。验证:取反加一得 `00011001` (25),即结果正确表示了 $-25$。
21. **答案:B**
- 注意**算术右移和逻辑右移是不一样的**,其核心区别在于**高位补位规则不同**‌,算术右移需要补符号位保持符号不变,而逻辑右移统一补0。‌‌**我们使用`<< >>` 运算符的时候,其实执行的都是算术左移、右移。**
- **算术左移的反码、补码规则**:**高位丢弃,低位补 0。**
- **算术右移的反码、补码规则**:同样采用**算术右移**。规则是:**高位补==符号位==,低位丢弃**。
- **算术右移的规则说明**:因为需要保持负数的性质,所以右移时高位对于负数而言需要**补 1**。
| 编码方式 | 负数左移 `<<` | 负数右移 `>>` (算术右移) |
| :-------- | :------------ | :----------------------- |
| **补码 ** | 低位**补 0** | 高位**补符号位 (1)** |
| **反码** | 低位**补 0** | 高位**补符号位 (1)** |
- 初始二进制串为 `11110000` ($-16$)。
- 执行算术右移时,整个位串向右移动,空出的高位必须用**原来的符号位**(这里是 `1`)来填充,以保持负数性质不变。
- 右移两位:`11110000` $\rightarrow$ `11111100`。
- `11111100` 对应的十进制数是 $-4$。这体现了算术右移对于负数同样具有“除以 $2^n$ 并向下取整”的数学效果($-16 \div 2^2 = -4$)。
23. **答案:C**
- 先执行有符号补码加法:`(-2) + (-3) = -5`。
- 求 $-5$ 的二进制位模式:$+5$ 是 `00000101`,取反加一得到 `11111011`。
- 将 `11111011` 作为一个**无符号整数**来读取:它的值是 $128+64+32+16+8+0+2+1 = 251$。(或者快速计算:无符号全 1 是 255,这里少了代表 4 的那一位,所以是 $255 - 4 = 251$)。
#### 题型四:符号扩展、移位与综合
23. **答案:D**
在进行位宽扩展(例如从 8 位扩展到 16 位)时,为了保证补码所代表的数值大小和正负号都不变,必须进行**符号扩展**。对于负数,其符号位(最高位)是 `1`,因此新增的高位必须全部用 `1` 来填充。**如果是正数,符号位是 `0`,高位就全补 `0`。**
24. **答案:A**
8 位补码 `11110110` 是一个负数,其符号位为 1。将其扩展为 16 位时,新增的 8 个高位全部用符号位 1 填充。结果为 `1111111111110110`。
25. **答案:C**
算术右移在移位的同时,需要保持数的符号不变。对于补码,这意味着右移时,空出来的高位必须用原始的符号位填充。`11111000` 是负数,符号位为 1,右移一位后,最高位补 1,得到 `11111100`。
26. **答案:D**
- **逻辑右移**:无论数的符号如何,右移后空出来的高位总是补 0。主要用于无符号数。
- **算术右移**:右移后空出来的高位用原始的符号位填充。主要用于有符号数,能保持除以 2 的算术效果。
27. **答案:`11110000`**
求 $-16$ 的补码:
- $+16$ 的 8 位二进制:`00010000`。
- 按位取反:`11101111`。
- 末位加 1:`11110000`。
28. **答案:B**
8 位补码 `11111111` 是负数。求其值:连同符号位取反得到 `00000000`,再加 1 得到 `00000001`,即 1。所以原值为 $-1$。
29. **答案:C**
在 $n$ 位补码中,`1000...0` 这个位模式是唯一一个没有对应正数的负数,它表示的是该位宽下能表示的最小负数,即 $-2^{n-1}$。
30. **答案:D**
- 首先,将十进制 200 转换为 8 位无符号二进制:$200 = 128 + 64 + 8 = (11001000)_2$。
- 然后,将位串 `11001000` 按照 8 位补码规则解释。最高位是 1,说明它是一个负数。
- 求其值:连同符号位取反为 `00110111`,再加 1 为 `00111000`。
- `00111000` 转换为十进制是 $32 + 16 + 8 = 56$。所以原值为 $-56$。
@@ -0,0 +1,133 @@
<center><font size="6"><b>NOIP/CSP 初赛专题训练</b></font></center>
<center><font size="5"><b>1.9 原码、补码、反码</b></font></center>
### 姓名:\_\_\_\_\_\_\_\_\_\_\_\_
---
### **题型一: 表示范围与基本概念**
1. ( ) 8 位无符号整数的取值范围是?
A. $0 \sim 255$ B. $-128 \sim 127$
C. $-127 \sim 127$ D. $0 \sim 256$
2. ( ) 8 位二进制补码整数的取值范围是?
A. $-128 \sim 128$ B. $-128 \sim 127$
C. $-127 \sim 127$ D. $0 \sim 255$
3. ( ) 8 位原码整数可表示的范围是?
A. $0 \sim 255$ B. $-128 \sim 128$
C. $-127 \sim 127$ D. $-128 \sim 127$
4. ( ) 下列表示法中,零只有一种编码的是?
A. 原码 B. 反码
C. 原码和反码 D. 补码
5. ( ) 正整数的原码、反码和补码?
A. 完全相同 B. 符号位不同
C. 补码要逐位取反 D. 反码要加一
6. 16 位无符号整数最多可表示 \_\_\_\_\_\_\_\_\_\_\_\_ 个不同的数。
7. ( ) 16 位补码整数的最小值是?
A. $0$ B. $-65535$
C. $-32768$ D. $-32767$
8. ( ) 在 8 位原码中,`10000000` 表示?
A. $-128$ B. $0$ 的唯一编码
C. $128$ D. 负零
---
### **题型二: 原码、反码与补码转换**
9. ( ) 十进制 $+37$ 的 8 位补码是?
A. `10100101` B. `11011010`
C. `00100101` D. `11011011`
10. ( ) 十进制 $-37$ 的 8 位补码是?
A. `00100101` B. `11011011`
C. `10100101` D. `11011010`
11. ( ) 十进制 $-64$ 的 8 位补码是?
A. `10111111` B. `01000000`
C. `11000000` D. `11000001`
12. ( ) 十进制 $-18$ 的 8 位反码是?
A. `11101101` B. `11101110`
C. `10010010` D. `00010010`
13. $-21$ 的 8 位原码为 \_\_\_\_\_\_\_\_\_\_\_\_。
14. ( ) 把 8 位补码 `11110110` 解释为十进制整数,结果是?
A. $246$ B. $10$
C. $-11$ D. $-10$
15. ( ) 把 8 位补码 `10000001` 解释为十进制整数,结果是?
A. $-127$ B. $129$
C. $127$ D. $-128$
16. 8 位补码 `10110110` 对应的十进制数为 \_\_\_\_\_\_\_\_\_\_\_\_。
---
### **题型三: 补码运算**
17. ( ) 按 8 位补码机器运算,计算 $45 + (-20)$ 得到的二进制结果是?
A. `00011001` B. `11100111`
C. `00111001` D. `00011010`
18. ( ) 在计算机底层,8 位补码减法运算 $15 - 20$ 的执行过程实际等价于?
A. $15$ 的补码 加上 $20$ 的原码
B. $15$ 的补码 加上 $-20$ 的补码
C. $15$ 的反码 加上 $20$ 的反码
D. $15$ 的补码 减去 $-20$ 的补码
19. ( ) 对于 8 位补码变量 `x`,在不考虑边界值的情况下,表达式 `~x + 1`(按位取反后加一)的数学意义是?
A. $x - 1$ B. $x + 1$
C. 取绝对值 $|x|$ D. 取相反数 $-x$
20. ( ) 按 8 位补码运算,$-10 + (-15)$ 的结果位模式是?
A. `11100111` B. `00011001`
C. `11101000` D. `11110111`
21. ( ) 在 8 位补码表示法中,对二进制串 `11110000`(即十进制 $-16$)执行算术右移两位(`>> 2`),得到的新位模式代表的十进制数是?
A. $-8$ B. $-4$
C. $60$ D. $12$
22. ( ) 在 8 位计算机中,执行补码加法 `(-2) + (-3)`。若将得到的二进制结果按**无符号**整数解释,其十进制值为?
A. $5$ B. $-5$
C. $251$ D. $253$
---
### **题型四: 符号扩展、移位与综合**
23. ( ) 把 8 位补码负数扩展为 16 位时,应在高位补?
A. 固定补 0 B. 交替补 0 和 1
C. 最低位 D. 符号位 1
24. ( ) 把 8 位补码 `11110110` 符号扩展为 16 位,结果是?
A. `1111111111110110` B. `0000000011110110`
C. `1111011000000000` D. `0000000010001010`
25. ( ) 在采用**算术右移**的补码机器中,8 位 `11111000` 右移一位得到?
A. `11110000` B. `00011111`
C. `11111100` D. `01111100`
26. ( ) 逻辑右移与算术右移的主要区别在于?
A. 一个向左一个向右 B. 逻辑右移只能用于十进制
C. 算术右移不移动最低位 D. 逻辑右移高位补 0,算术右移高位补符号位
27. 8 位补码整数 $-16$ 的位模式为 \_\_\_\_\_\_\_\_\_\_\_\_。
28. ( ) 8 位补码 `11111111` 对应?
A. $0$ B. $-1$
C. $255$ D. $-127$
29. ( ) 若一个 $n$ 位补码数的最高位与其余位全部相反,即形如 `1000...0`,它表示?
A. $2^{n-1}$ B. $-1$
C. $-2^{n-1}$ D. $0$
30. ( ) 已知某 8 位二进制序列作为无符号整数解释时,其对应的十进制值为 200。若将该同一序列视为有符号整数的补码表示,其代表的十进制真值为?
A. $56$ B. $200$ C. $-200$ D. $-56$
@@ -0,0 +1,187 @@
# NOI CSP-J 初赛专项模拟题:计算机的基本构成
## 一、单项选择题
1. 世界上第一台电子计算机 ENIAC 诞生于 1946 年,它主要使用的逻辑元件是( )。
A. 晶体管
B. 电子管
C. 集成电路
D. 超大规模集成电路
2. 提出“存储程序”与“二进制”思想,奠定了现代计算机基本结构理论基础的科学家是( )。
A. 艾伦·图灵 (Alan Turing)
B. 冯·诺依曼 (John von Neumann)
C. 克劳德·香农 (Claude Shannon)
D. 戈登·摩尔 (Gordon Moore)
3. 计算机硬件系统由五大基本部件组成,它们是( )。
A. 主机、显示器、键盘、鼠标、音箱
B. 控制器、运算器、存储器、输入设备、输出设备
C. CPU、内存、硬盘、显卡、主板
D. 硬件系统、软件系统、操作系统、网络、数据
4. 微型计算机的中央处理器(CPU)主要由( )组成。
A. 运算器和存储器
B. 控制器和存储器
C. 运算器和控制器
D. 运算器、控制器和内存
5. 下列存储器中,断电后数据会丢失,再次通电无法恢复的是( )。
A. 硬盘 (Hard Disk)
B. 只读存储器 (ROM)
C. 随机存取存储器 (RAM)
D. 闪存 (Flash Memory)
6. 在计算机中,连接 CPU、内存和外设之间传送信息的公共通道称为( )。
A. 电缆
B. 寄存器
C. 总线 (Bus)
D. 接口
7. 计算机的运算速度主要取决于( )。
A. 磁盘容量和存取速度
B. 操作系统软件的优劣
C. 字长和主频
D. 显示器的分辨率
8. 下列设备中,属于输出设备的是( )。
A. 扫描仪
B. 麦克风
C. 绘图仪
D. 摄像头
9. 某计算机的 CPU 主频为 2.4GHz,这里的“GHz”是( )的单位。
A. 时间
B. 速度
C. 频率
D. 容量
10. 计算机存储容量的基本单位是( )。
A. 位 (Bit)
B. 字节 (Byte)
C. 字 (Word)
D. 赫兹 (Hz)
11. 在计算机存储体系中,访问速度最快的是( )。
A. 硬盘
B. 内存 (DRAM)
C. 高速缓冲存储器 (Cache)
D. 光盘
12. 计算机软件系统主要分为( )两大类。
A. 操作系统和数据库系统
B. 系统软件和应用软件
C. 编译软件和编辑软件
D. 高级语言和机器语言
13. 完整的计算机系统应包括( )。
A. 运算器、控制器和存储器
B. 主机和外部设备
C. CPU 和内存
D. 硬件系统和软件系统
14. 下列软件中,属于系统软件的是( )。
A. Excel
B. 微信 (WeChat)
C. Linux
D. Python 解释器
15. 如果一台计算机的地址总线宽度为 16 位,那么它理论上最大能寻址的内存空间是( )。
A. 16 KB
B. 32 KB
C. 64 KB
D. 1 MB
16. 计算机指令主要由( )两部分组成。
A. 操作码和操作数
B. 数据和地址
C. 运算符和结果
D. 输入和输出
17. 1 MB (兆字节) 等于( )。
A. 1000 KB
B. 1024 KB
C. 1024 GB
D. 1000 Bit
18. 在微机中,VGA、HDMI 通常指的是( )的接口。
A. 硬盘
B. 打印机
C. 显示器
D. 网络
19. 将高级语言编写的源程序翻译成目标程序(机器码)的程序称为( )。
A. 编辑程序
B. 编译程序
C. 链接程序
D. 调试程序
20. 现代计算机中,数据和指令在内存中都是以( )形式存储的。
A. 十进制
B. 二进制
C. 十六进制
D. ASCII 码
---
## 二、答案与解析
1. **答案:B**
* **解析**:ENIAC 是第一代计算机,使用电子管作为逻辑元件。第二代是晶体管,第三代是集成电路,第四代是大规模集成电路。
2. **答案:B**
* **解析**:冯·诺依曼提出了“存储程序”原理,即程序和数据都以二进制形式存放在存储器中,计算机自动执行。这确立了现代计算机的体系结构。
3. **答案:B**
* **解析**: 冯·诺依曼结构规定计算机硬件由运算器、控制器、存储器、输入设备、输出设备五大部分组成。
4. **答案:C**
* **解析**:CPU(中央处理器)的核心部件是运算器(ALU)和控制器(CU),现代 CPU 内部还包含寄存器和 Cache,但主要组成部分是前两者。
5. **答案:C**
* **解析**:RAM 是随机存取存储器,属于易失性存储器,断电后数据丢失。ROM、硬盘、闪存都是非易失性的。
6. **答案:C**
* **解析**:总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线。
7. **答案:C**
* **解析**:字长决定了 CPU 一次能处理的数据位数,主频决定了 CPU 的时钟节拍快慢,两者是影响运算速度的最关键硬件指标。
8. **答案:C**
* **解析**:绘图仪用于打印大幅图纸,属于输出设备。扫描仪、麦克风、摄像头都是向计算机输入信息的设备。
9. **答案:C**
* **解析**:GHz 是频率单位(吉赫兹),表示每秒钟震荡的次数,用于衡量 CPU 的时钟频率。
10. **答案:B**
* **解析**:Bit(位)是最小的信息单位,但 Byte(字节)是基本的存储和寻址单位。1 Byte = 8 Bits。
11. **答案:C**
* **解析**:存储器速度由快到慢排序通常为:CPU 寄存器 > Cache > 内存 (RAM) > 硬盘/光盘。
12. **答案:B**
* **解析**:软件系统总体分为系统软件(如操作系统、驱动程序)和应用软件(如办公软件、游戏)。
13. **答案:D**
* **解析**:计算机系统由“硬件系统”和“软件系统”两大部分组成,“裸机”无法工作。
14. **答案:C**
* **解析**:Linux 是操作系统,属于系统软件。Excel、微信是应用软件。Python 解释器属于语言处理程序(广义上也属于系统软件范畴,但在 CSP-J 选项中,操作系统是最典型的系统软件,若无操作系统选项,语言处理程序可选;但此处 Linux 为最核心的系统软件)。
15. **答案:C**
* **解析**:寻址范围计算公式为 $2^N$。$N=16$,则 $2^{16} = 65536$ 字节 = $64$ KB。
16. **答案:A**
* **解析**:一条指令通常包括操作码(做什么操作)和操作数(对什么数据进行操作,通常是数据的地址)。
17. **答案:B**
* **解析**:计算机中存储单位采用 1024 进制($2^{10}$)。$1 \text{MB} = 1024 \text{KB}$,$1 \text{KB} = 1024 \text{Byte}$。
18. **答案:C**
* **解析**:VGA 和 HDMI 都是常见的视频传输接口,用于连接显示器或投影仪。
19. **答案:B**
* **解析**:编译程序(Compiler)的作用是将高级语言源程序整体翻译成机器语言目标程序;解释程序则是逐条翻译执行。
20. **答案:B**
* **解析**:在计算机内部,无论是数据(如数字、字符、图像)还是指令,最终都是以二进制代码(0 和 1)的形式存储和处理的。
@@ -0,0 +1,248 @@
# NOI CSP-J 初赛专项模拟题:操作系统的基本概念及其常见操作
## 一、单项选择题
1. 计算机系统中,负责管理和控制计算机硬件与软件资源、合理组织计算机工作流程以及方便用户使用的程序集合称为( )。
A. 应用软件
B. 操作系统
C. 数据库管理系统
D. 编译程序
2. 下列软件中,不属于操作系统的是( )。
A. Windows 11
B. Unix
C. Python
D. HarmonyOS
3. 关于 Linux 操作系统,下列说法正确的是( )。
A. Linux 是单用户单任务操作系统
B. Linux 主要用于个人娱乐,不适合用于服务器
C. Linux 是开源的、免费的操作系统
D. Linux 系统中文件扩展名决定了文件的类型,不可随意更改
4. 在 Windows 系统中,通常用来表示“纯文本文件”的扩展名是( )。
A. .jpg
B. .exe
C. .txt
D. .zip
5. 在 Windows 操作系统中,下列文件名命名非法的是( )。
A. My_File.txt
B. 2023-Data.doc
C. A*B?.ppt
D. CSP J 2023
6. 在 Windows 资源管理器或多数文本编辑器中,撤销上一步操作的快捷键通常是( )。
A. Ctrl + C
B. Ctrl + V
C. Ctrl + Z
D. Ctrl + A
7. 小明在整理电脑文件时,想把文件 A 从“D:\学习资料”文件夹移动到“E:\备份”文件夹,他应该进行的操作是( )。
A. 剪切 -> 粘贴
B. 复制 -> 粘贴
C. 删除 -> 恢复
D. 重命名
8. 某文件的大小显示为 2GB,它大约等于多少 MB?( )
A. 2000 MB
B. 2048 MB
C. 1000 MB
D. 1024 MB
9. 在 Windows 中,若选中一个文件并按住 Shift 键同时也按下 Delete 键,则该文件会( )。
A. 进入回收站,可以恢复
B. 被永久删除,不进入回收站(常规手段无法恢复)
C. 被复制到剪贴板
D. 被重命名
10. 我们常说的“64位操作系统”中的“64位”指的是( )。
A. 内存容量
B. CPU 的字长(一次能处理的数据位数)
C. 硬盘速度
D. 显示器色彩深度
11. 在操作系统中,目录(文件夹)结构通常采用( )数据结构来组织。
A. 线性表
B. 树形结构
C. 网状结构
D. 环形结构
12. 在 Linux 系统中,区分大小写是其重要特性之一。下列说法正确的是( )。
A. Test.cpp 和 test.cpp 在 Linux 下是同一个文件
B. Test.cpp 和 test.cpp 在 Linux 下是两个不同的文件
C. 只有在 Windows 下它们才是不同的文件
D. 只有在扩展名不同时才是不同文件
13. 下列选项中,主要用于智能手机和平板电脑的移动操作系统是( )。
A. iOS
B. MS-DOS
C. Linux RedHat
D. Windows Server
14. 如果一个文件被设置为“只读”属性,那么用户通常( )。
A. 不能打开该文件
B. 可以查看但不能修改保存该文件
C. 不能复制该文件
D. 看不到该文件
15. 现代操作系统(如 Windows, Linux, macOS)大都支持“多任务处理”,这意味着( )。
A. 计算机只能同时运行一个程序
B. 计算机可以同时运行多个程序,CPU 分时轮流处理
C. 需要多个 CPU 才能运行多个程序
D. 只有联网后才能运行多个程序
16. 在 Windows 系统中,想要快速切换当前正在运行的不同应用程序窗口,常用的快捷键是( )。
A. Alt + Tab
B. Ctrl + Shift
C. Windows + D
D. Ctrl + Alt + Del
17. 当我们新买了一台打印机连接到电脑上,通常需要安装“驱动程序”才能正常打印,驱动程序的作用是( )。
A. 提高打印机的打印速度
B. 充当操作系统与硬件设备之间的翻译和桥梁
C. 给打印机供电
D. 是一类文字处理软件
18. 操作系统中,“剪贴板”(Clipboard)的作用是作为临时存储区域,它通常位于计算机的( )中。
A. 硬盘
B. ROM
C. 内存(RAM)
D. 回收站
19. 下列哪项不属于操作系统的核心功能?( )
A. 处理器(CPU)管理
B. 编写计算机源代码
C. 存储器(内存)管理
D. 设备管理
20. 常见的用户界面主要分为 GUI(图形用户界面)和 CLI(命令行界面)。下列操作系统中,以提供直观的图形用户界面(GUI)而著称的是( )。
A. MS-DOS
B. Windows 10
C. 原始的 Unix Shell
D. BIOS 设置界面
------
## 答案与解析
1. **答案:B**
- **解析:** 操作系统的标准定义。它是管理计算机硬件与软件资源的程序集合,是用户和计算机的接口。
2. **答案:C**
- **解析:** Python 是一种编程语言及其解释器,属于语言处理程序(系统软件的一种,但不是操作系统)。A、B、D 均为操作系统。
3. **答案:C**
- **解析:** Linux 是著名的开源、免费操作系统,支持多用户多任务,广泛用于服务器。Linux 下文件扩展名不是强制的,虽然习惯上会用扩展名区分,但改了扩展名不影响文件内容和类型。
4. **答案:C**
- **解析:** .txt 是纯文本;.jpg 是图片;.exe 是可执行程序;.zip 是压缩包。
5. **答案:C**
- **解析:** Windows 文件名中不能包含下列字符:`\ / : * ? " < > |`。选项 C 包含了 `*` 和 `?`,是非法的。
6. **答案:C**
- **解析:** 通用快捷键:Ctrl+C 复制,Ctrl+V 粘贴,Ctrl+X 剪切,Ctrl+Z 撤销,Ctrl+A 全选。
7. **答案:A**
- **解析:** 移动 = 剪切 + 粘贴。原位置文件消失,新位置出现。复制 = 复制 + 粘贴,原文件保留。
8. **答案:B**
- **解析:** 计算机存储单位换算率为 1024。$1 \text{GB} = 1024 \text{MB}$,所以 $2 \text{GB} = 2 \times 1024 = 2048 \text{MB}$。
9. **答案:B**
- **解析:** 这是一个重要的操作常识。直接 Delete 会放入回收站(可后悔);Shift + Delete 是物理删除(不进回收站,难以恢复)。
10. **答案:B**
- **解析:** 操作系统的位数取决于 CPU 的指令集架构和寻址能力。64位指 CPU 一次能处理 64 位二进制数据。
11. **答案:B**
- **解析:** 文件系统的目录结构是从根目录开始,逐级向下分支,这是一种典型的“树形结构”。
12. **答案:B**
- **解析:** 重要考点。Windows 文件系统通常不区分大小写。Linux 文件系统(Ext4等)严格区分大小写,所以 Test.cpp 和 test.cpp 是两个不同的文件。
13. **答案:A**
- **解析:** iOS 是苹果公司的移动操作系统。MS-DOS 是早期的命令行系统;RedHat 是服务器版 Linux;Windows Server 是服务器系统。
14. **答案:B**
- **解析:** “只读”属性意味着可以读取(Read)内容,但不能写入(Write/Modify)保存。
15. **答案:B**
- **解析:** 单核 CPU 在同一时刻只能执行一条指令。多任务处理是通过操作系统的调度,让 CPU 在不同程序间快速切换(分时),让人感觉是同时运行。
16. **答案:A**
- **解析:** Alt + Tab 是标准的切换窗口快捷键。Win + D 是显示桌面;Ctrl + Alt + Del 通常用于打开任务管理器或安全界面。
17. **答案:B**
- **解析:** 驱动程序(Driver)是硬件厂商提供的,让操作系统能够控制和使用该硬件的接口程序。没有驱动,操作系统无法识别或控制硬件。
18. **答案:C**
- **解析:** 剪贴板是内存(RAM)中的一块区域,用于临时存放交换的数据。如果电脑断电或重启,剪贴板中的内容通常会丢失。
19. **答案:B**
- **解析:** 操作系统的五大基本功能包括:处理器管理、存储器管理、设备管理、文件管理和作业管理。编写源代码是程序员的工作,使用的是编辑器或IDE,不属于操作系统的内核功能。
20. **答案:B**
- **解析:** GUI(Graphical User Interface)指图形用户界面,Windows 是典型的 GUI 操作系统。MS-DOS 和 Unix Shell 主要是 CLI(命令行界面)。
@@ -0,0 +1,190 @@
# NOI CSP-J 初赛专项模拟题:计算机网络与Internet的基本概念
## 单项选择题
1. **计算机网络最突出的优势是( )。**
A. 提高计算机的运算速度
B. 实现资源共享和信息传递
C. 提高计算机的存储容量
D. 增加计算机的稳定性
2. **按照网络的覆盖范围,可以将计算机网络分为局域网(LAN)、城域网(MAN)和广域网(WAN)。下列关于这三者的描述,正确的是( )。**
A. 覆盖范围:LAN > MAN > WAN
B. 传输速率:WAN 通常高于 LAN
C. Internet 是世界上最大的广域网
D. 学校机房的网络通常属于城域网
3. **在计算机网络拓扑结构中,若中央节点发生故障将导致整个网络瘫痪,这种结构是( )。**
A. 总线型
B. 环型
C. 星型
D. 网状型
4. **目前互联网广泛使用的 TCP/IP 协议中,IP 地址(IPv4)是由( )位二进制数组成的。**
A. 16
B. 32
C. 64
D. 128
5. **下列 IP 地址中,格式正确的是( )。**
A. 192.168.1
B. 202.102.300.1
C. 10.0.0.1
D. 172.16.256.1
6. **为了解决 IPv4 地址枯竭的问题,新一代互联网协议 IPv6 应运而生。IPv6 采用的地址长度是( )。**
A. 64位
B. 128位
C. 256位
D. 512位
7. **在 Internet 上,用于将域名(如 [www.noi.cn](https://www.roi.com))转换为对应的 IP 地址(如 202.10.1.1)的服务系统是( )。**
A. URL
B. DNS
C. FTP
D. HTTP
8. **下列关于域名的说法中,错误的是( )。**
A. 域名是 IP 地址的字符形式,便于人们记忆
B. 域名中的 .com 通常代表商业机构,.edu 代表教育机构
C. 域名具有层次结构,顶级域名在最右侧
D. 一个 IP 地址只能对应一个域名,一个域名也只能对应一个 IP 地址
9. **统一资源定位符(URL)用于标识互联网上的资源位置。在 URL `http://www.example.com/index.html` 中,`http` 代表的是( )。**
A. 主机名
B. 协议名
C. 路径
D. 文件名
10. **电子邮件(E-mail)是互联网最基本的服务之一。下列电子邮件地址格式正确的是( )。**
A. https://www.google.com/search?q=user.gmail.com
B. user#gmail.com
C. user@gmail.com
D. [www.user.gmail.com](https://www.google.com/search?q=https://www.user.gmail.com)
11. **在电子邮件收发过程中,通常用于发送邮件的协议是( ),用于接收邮件的协议是( )。**
A. POP3; SMTP
B. SMTP; POP3
C. HTTP; FTP
D. TCP; IP
12. **超文本标记语言的英文缩写是( ),它是制作网页的基础。**
A. HTTP
B. HTML
C. URL
D. WWW
13. **下列 IP 地址中,属于“C类”地址且通常用于局域网内部(私有地址)的是( )。**
A. 10.0.0.1
B. 172.16.1.1
C. 192.168.1.100
D. 127.0.0.1
14. **Internet 提供的服务多种多样,其中 FTP 服务主要用于( )。**
A. 远程登录
B. 网页浏览
C. 文件传输
D. 电子公告板
15. **远程登录允许用户通过网络控制远程计算机,就像坐在该计算机面前一样。远程登录使用的标准协议是( )。**
A. Telnet
B. FTP
C. SMTP
D. UDP
16. **网页浏览器(Browser)是用户访问万维网的工具。下列软件中不属于浏览器的是( )。**
A. Google Chrome
B. Microsoft Edge
C. Mozilla Firefox
D. Apache HTTP Server
17. **在 TCP/IP 协议簇中,ping 命令常用于测试网络的连通性。它利用的是( )协议。**
A. TCP
B. ICMP
C. UDP
D. ARP
18. **关于万维网(WWW),下列说法错误的是( )。**
A. WWW 是 World Wide Web 的缩写
B. WWW 信息资源主要以网页形式呈现
C. WWW 就是互联网(Internet)的代名词
D. WWW 使用 HTTP 协议传输数据
19. **在一个局域网中,多台计算机需要通过一条电话线或光纤接入 Internet,通常需要一个设备来进行网络地址转换(NAT)和路由转发,这个设备是( )。**
A. 交换机 (Switch)
B. 路由器 (Router)
C. 集线器 (Hub)
D. 网卡 (NIC)
20. **IP 地址 127.0.0.1 是一个特殊的地址,它通常被称为( )。**
A. 广播地址
B. 网络地址
C. 回环地址(Localhost)
D. 网关地址
---
## 二、答案与解析
1. **答案:B**
* **解析:** 计算机网络的主要目的是实现硬件、软件和数据资源的共享以及用户之间的信息传递。
2. **答案:C**
* **解析:** A项中 WAN 的覆盖范围最大;B项中通常局域网(LAN)的传输速率高于广域网(WAN),因为距离短、介质好;D项学校机房通常是局域网(LAN),整个城市的网络才可能是城域网(MAN)。Internet 是全球最大的广域网。
3. **答案:C**
* **解析:** 星型拓扑结构由一个中心节点(如交换机)和若干外围节点组成,所有数据都需经过中心节点。如果中心节点故障,全网瘫痪。总线型和环型某处断开可能会影响部分或全部,但星型对中心节点的依赖最强。
4. **答案:B**
* **解析:** IPv4 地址由 32 位二进制数组成,通常用点分十进制表示(如 192.168.1.1)。IPv6 是 128 位。
5. **答案:C**
* **解析:** IP 地址由 4 段数字组成,每段范围是 0-255。A项只有3段;B项 300 超出了 255;D项 256 超出了 255。C项 10.0.0.1 合法。
6. **答案:B**
* **解析:** IPv6(Internet Protocol Version 6)采用 128 位地址长度,号称可以为地球上的每一粒沙子分配一个 IP 地址。
7. **答案:B**
* **解析:** DNS(Domain Name System,域名系统)的作用就是建立域名和 IP 地址之间的映射关系,方便用户访问。
8. **答案:D**
* **解析:** 域名和 IP 地址并不是严格的一一对应关系。一台服务器(一个 IP)可以托管多个域名;大型网站(一个域名)也可以对应多个 IP(负载均衡)。
9. **答案:B**
* **解析:** URL 格式为 `协议://主机名/路径/文件名`。这里 `http` 是超文本传输协议。
10. **答案:C**
* **解析:** 电子邮件的标准格式是 `用户名@主机域名`。
11. **答案:B**
* **解析:** 发信通常使用 SMTP(简单邮件传输协议);收信通常使用 POP3(邮局协议第3版)或 IMAP。
12. **答案:B**
* **解析:** HTML(HyperText Markup Language)是超文本标记语言。HTTP 是传输协议;URL 是地址;WWW 是万维网服务。
13. **答案:C**
* **解析:** * A类私有地址:10.0.0.0 - 10.255.255.255
* B类私有地址:172.16.0.0 - 172.31.255.255
* C类私有地址:192.168.0.0 - 192.168.255.255
* C 选项 192.168.1.100 是典型的 C 类私有地址。
14. **答案:C**
* **解析:** FTP(File Transfer Protocol)是文件传输协议,用于在网络上传输文件。
15. **答案:A**
* **解析:** Telnet 是 Internet 远程登录服务的标准协议。
16. **答案:D**
* **解析:** Apache HTTP Server 是一种 Web 服务器软件,用于提供网页服务,而不是用户用来浏览网页的客户端浏览器。Chrome、Edge、Firefox 都是浏览器。
17. **答案:B**
* **解析:** ping 命令基于 ICMP(Internet Control Message Protocol,互联网控制报文协议)工作,用于检测目标主机是否可达。
18. **答案:C**
* **解析:** WWW(万维网)只是运行在 Internet 上的一种服务(应用层),Internet 还包括 E-mail、FTP、Telnet 等其他服务,两者不能等同。
19. **答案:B**
* **解析:** 路由器(Router)的主要功能是连接不同的网络(如局域网和互联网),并进行数据包的路由转发和地址转换(NAT)。
20. **答案:C**
* **解析:** 127.0.0.1 是回环地址(Loopback Address),代表计算机本身,常用于本机测试。
@@ -0,0 +1,151 @@
# NOI CSP-J 初赛专项模拟题:计算机历史、应用与NOI活动
## 一、单项选择题
1. **世界上第一台通用电子数字计算机 ENIAC 诞生于( )。**
A. 1936年
B. 1946年
C. 1956年
D. 1964年
2. **被后人誉为“计算机之父”,提出了“存储程序”概念的科学家是( )。**
A. 艾伦·图灵 (Alan Turing)
B. 冯·诺依曼 (John von Neumann)
C. 克劳德·香农 (Claude Shannon)
D. 查尔斯·巴贝奇 (Charles Babbage)
3. **计算机的发展经历了四个时代,划分这四个时代的主要依据是( )。**
A. 计算机的运算速度
B. 计算机的物理体积
C. 构成计算机的逻辑元件(电子器件)
D. 计算机的编程语言
4. **著名的“摩尔定律”(Moore's Law)指出,集成电路芯片上所集成的晶体管数目,大约每隔( )个月就翻一番。**
A. 6
B. 12
C. 18
D. 36
5. **中国计算机学会(CCF)于( )年创办了全国青少年信息学奥林匹克竞赛(NOI)。**
A. 1980
B. 1984
C. 1989
D. 1995
6. **在计算机应用领域中,CAD 的中文含义是( )。**
A. 计算机辅助教学
B. 计算机辅助设计
C. 计算机辅助制造
D. 计算机辅助测试
7. **被认为是世界上第一位程序员的女性科学家是( )。**
A. 葛丽丝·霍普 (Grace Hopper)
B. 埃达·洛夫莱斯 (Ada Lovelace)
C. 玛格丽特·汉密尔顿 (Margaret Hamilton)
D. 希拉里·梅森 (Hilary Mason)
8. **1984年,邓小平同志在上海观看小学生操作计算机程序演示后,提出了( )的著名论断,极大地推动了中国计算机教育的发展。**
A. 计算机要从娃娃抓起
B. 科学技术是第一生产力
C. 普及计算机教育
D. 学习编程,面向未来
9. **目前,NOI 系列活动(包括 CSP-J/S, NOIP, NOI 等)中,官方支持的唯一的程序设计语言是( )。**
A. C
B. Pascal
C. Python
D. C++
10. **IOI 是国际信息学奥林匹克竞赛的缩写,第一届 IOI 于 1989 年在( )举行。**
A. 中国北京
B. 美国华盛顿
C. 保加利亚布拉维茨
D. 希腊雅典
11. **图灵奖(Turing Award)被誉为“计算机界的诺贝尔奖”,它是由( )设立的。**
A. IEEE(电气电子工程师学会)
B. ACM(美国计算机协会)
C. Intel 公司
D. 诺贝尔基金会
12. **第二代电子计算机使用的主要逻辑元件是( )。**
A. 电子管
B. 晶体管
C. 集成电路
D. 大规模集成电路
13. **关于 CSP-J/S,下列说法正确的是( )。**
A. 它是一项专业级别的程序员资格认证
B. 它的全称是“计算机软件能力认证”
C. 它分为 J 组(入门级)和 S 组(提高级)两个组别
D. 只有高中生才能参加 S 组
14. **人工智能(AI)是当前计算机应用的热点之一。最早提出判断机器是否具有智能的测试方法,被称为( )。**
A. 冯·诺依曼测试
B. 摩尔测试
C. 图灵测试
D. 香农测试
15. **中国自主研发的超级计算机在世界范围内享有盛誉,其中曾多次蝉联世界最快超级计算机榜首的是( )系列。**
A. 银河
B. 曙光
C. 也就是
D. 神威·太湖之光
16. **NOI 系列活动的主办单位是( )。**
A. 教育部
B. 中国科协
C. 中国计算机学会 (CCF)
D. 清华大学
---
## 二、答案与详细解析
1. **答案:B**
* **解析:** 世界上第一台通用电子数字计算机 ENIAC(埃尼阿克)于 1946 年在美国宾夕法尼亚大学诞生。
2. **答案:B**
* **解析:** 冯·诺依曼(John von Neumann)提出了“存储程序”原理和二进制思想,确立了现代计算机的基本结构,被称为“现代计算机之父”。艾伦·图灵被称为“计算机科学之父”和“人工智能之父”。
3. **答案:C**
* **解析:** 计算机发展的四个时代是根据物理器件(逻辑元件)来划分的:第一代(电子管)、第二代(晶体管)、第三代(中小规模集成电路)、第四代(大规模和超大规模集成电路)。
4. **答案:C**
* **解析:** 戈登·摩尔提出的摩尔定律指出,集成电路上可容纳的晶体管数目,约每隔 18-24 个月便会增加一倍,性能也将提升一倍。选项中 18 最为准确。
5. **答案:B**
* **解析:** 1984 年,中国计算机学会(CCF)创办了首届全国青少年信息学奥林匹克竞赛(NOI)。
6. **答案:B**
* **解析:** CAD (Computer Aided Design) 是计算机辅助设计;CAM 是计算机辅助制造;CAI 是计算机辅助教学。
7. **答案:B**
* **解析:** 埃达·洛夫莱斯(Ada Lovelace),拜伦之女,她为巴贝奇的分析机编写了算法,被公认为世界上第一位程序员。
8. **答案:A**
* **解析:** 1984 年 2 月 16 日,邓小平在上海观看小学生演示后说:“计算机的普及要从娃娃抓起。”这句话成为了中国计算机教育发展的指导方针。
9. **答案:D**
* **解析:** 根据 CCF 的规定,自 2022 年起,NOI 系列活动(包括 CSP-J/S)不再支持 Pascal 和 C 语言,C++ 成为唯一的比赛语言。
10. **答案:C**
* **解析:** 第一届国际信息学奥林匹克竞赛(IOI)于 1989 年在保加利亚的布拉维茨举行。
11. **答案:B**
* **解析:** 图灵奖由美国计算机协会(ACM)设立,以表彰在计算机科学领域做出杰出贡献的科学家,是计算机界的最高荣誉。
12. **答案:B**
* **解析:** 第一代是电子管;第二代是晶体管;第三代是集成电路;第四代是大规模集成电路。
13. **答案:C**
* **解析:** CSP-J/S 是 CCF 组织的“非专业级软件能力认证”(Certified Software Professional - Junior/Senior)。A 错误,它是非专业的;B 错误,全称应包含“非专业级”;D 错误,中小学生均可参加任一组别,不限年级。
14. **答案:C**
* **解析:** 艾伦·图灵在 1950 年提出了“图灵测试”,如果在测试中,人类测试者无法区分对话的是机器还是人,则认为机器具有智能。
15. **答案:D**
* **解析:** “神威·太湖之光”曾多次位居全球超级计算机 TOP500 榜首,展示了中国在超算领域的强大实力。“天河”系列也曾夺冠。
16. **答案:C**
* **解析:** 全国青少年信息学奥林匹克竞赛(NOI)及 CSP-J/S 认证的主办单位均是中国计算机学会(CCF)。
@@ -0,0 +1,97 @@
# NOI CSP-J 初赛专项模拟题:计算机编码基础
## 一、单项选择题
1. **在计算机系统中,能被计算机接受和处理的符号的集合被称为( )。**
A. 编码
B. 数据
C. 信息
D. 比特
2. **计算机中表示信息的数据编码中的最小单位是( )。**
A. 字节 (Byte)
B. 比特 (Bit)
C. 字 (Word)
D. 字符 (Character)
3. **关于“字节”(Byte)的描述,根据所给资料,下列说法错误的是( )。**
A. 字节表示被处理的一组连续的二进制数字
B. 通常用 8 位二进制数字表示一个字节
C. 字节是存储器系统的最小存取单位
D. 一个字节由 7 个比特组成
4. **将各类符号、图形、图像和声音等非数值数据转换成计算机能识别的“0”和“1”表示的代码,这一过程称为( )。**
A. 运算
B. 存储
C. 编码
D. 交互
5. **ASCII 码的全称是( )。**
A. 国际信息交换标准代码
B. 美国国家信息交换标准代码
C. 欧洲计算机制造商协会代码
D. 通用多八位编码字符集
6. **标准的 ASCII 码采用( )位二进制编码,能表示( )种字符。**
A. 7; 128
B. 8; 256
C. 7; 256
D. 8; 128
7. **在 ASCII 码的存储中,虽然标准 ASCII 码只有 7 位,但它存储时通常占全一个字节(8位)。在基本的 ASCII 码中,最高位(b7)的值恒为( )。**
A. 1
B. 0
C. 随机
D. 与 b6 相同
8. **根据资料,ASCII 编码中数字“0”的十六进制值为 30H。那么数字“5”的 ASCII 码十六进制值是( )。**
A. 35H
B. 36H
C. 45H
D. 50H
9. **已知大写字母“A”的 ASCII 编码值为 41H,那么大写字母“D”的 ASCII 编码值是( )。**
A. 42H
B. 43H
C. 44H
D. 45H
10. **小写字母“a”的 ASCII 编码值为 61H,大写字母“A”的 ASCII 编码值为 41H。它们之间的差值是( )。**
A. 10H
B. 20H
C. 30H
D. 32H
---
## 二、答案与详细解析
1. **答案:B**
* **解析:** “数据”的定义就是能被计算机接受和处理的符号的集合。计算机处理的对象就是数据。
2. **答案:B**
* **解析:** 比特(Bit,Binary Digit)是二进制数位,是计算机表示信息的数据编码中的**最小单位**,只能是 0 或 1。
3. **答案:D**
* **解析:** 字节(Byte)是计算机存储的基本单位,通常由 **8** 个比特(bit)组成,而不是 7 个。
4. **答案:C**
* **解析:** 编码就是将各类现实世界的信息(如符号、图像、声音)转换成计算机能够识别的二进制代码(0 和 1)的过程。
5. **答案:B**
* **解析:** ASCII 是 **A**merican **S**tandard **C**ode for **I**nformation **I**nterchange 的缩写,意为美国国家信息交换标准代码。
6. **答案:A**
* **解析:** 标准的 ASCII 码使用 **7** 位二进制数来表示字符,因此它可以表示的状态(字符)总数为 种。
7. **答案:B**
* **解析:** ASCII 码占用一个字节(8位)进行存储,但标准 ASCII 码只用了低 7 位,最高位(第 8 位,b7)通常被置为 **0**。
8. **答案:A**
* **解析:** ASCII 码中数字字符是连续排列的。已知 '0' 的十六进制是 30H,'5' 在 '0' 后面第 5 个位置,所以 。
9. **答案:C**
* **解析:** 英文字母在 ASCII 表中也是按字母表顺序连续排列的。'A' 是 41H,'D' 是 'A' 后的第三个字母(A, B, C, D),所以 'D' = 。
10. **答案:B**
* **解析:** 小写字母 'a' (61H) 比大写字母 'A' (41H) 的 ASCII 值大。计算差值:。所有对应的大小写字母之间都相差 20H(即十进制的 32)。
@@ -0,0 +1,399 @@
# NOI CSP-J 初赛专项模拟题:程序基本语句
## 阅读程序 (程序输入不超过数组或字符串定义的范围,判断题正确填√,错误填×)
### (1)
```cpp
01 #include <iostream>
02 using namespace std;
03
04 int main() {
05 int x, y;
06 cin >> x >> y;
07 int ans = 1;
08 for (int i = 1; i <= y; i++) {
09 ans = ans * x;
10 ans = ans % 10;
11 }
12 cout << ans << endl;
13 return 0;
14 }
```
假设输入的 `x`, `y` 均为不超过 100 的正整数,完成下面的判断题和单选题:
**判断题**
1. 该程序的功能是计算 的值。( )
2. 程序的输出结果一定是一个小于 10 的整数。( )
3. 当输入为“2 3”时,输出为“8”。( )
**单选题**
4. 当输入为“12 2”时,输出为( )。
A. 2 B. 4 C. 24 D. 144
5. 当输入为“2 10”时,输出为( )。
A. 2 B. 4 C. 6 D. 8
---
### (2)
```cpp
01 #include <iostream>
02 using namespace std;
03
04 int main() {
05 int n;
06 cin >> n;
07 int a[105];
08 for(int i = 1; i <= n; i++) {
09 cin >> a[i];
10 }
11 int count = 0;
12 for(int i = 1; i <= n; i++) {
13 if(a[i] > 0 && a[i] % 2 == 0) {
14 count = count + a[i];
15 }
16 }
17 cout << count << endl;
18 return 0;
19 }
```
假设输入的 `n` 为不超过 100 的正整数,数组元素均为 `int` 范围内整数,完成下面的判断题和单选题:
**判断题**
6. 该程序统计的是数组中所有偶数的个数。( )
7. 如果数组中所有的数都是负数,输出结果为 0。( )
8. 第 13 行的 `a[i] > 0` 条件如果去掉,程序的输出结果对于任何输入都不会改变。( )
**单选题**
9. 当输入 `n=5`,数组元素为 `1 2 3 4 5` 时,输出为( )。
A. 2 B. 3 C. 6 D. 9
10. 当输入 `n=5`,数组元素为 `-2 -4 2 4 6` 时,输出为( )。
A. 12 B. 6 C. 0 D. -6
---
### (3)
```cpp
01 #include <iostream>
02 #include <string>
03 using namespace std;
04
05 int main() {
06 string s;
07 cin >> s;
08 int len = s.length();
09 for (int i = 0; i < len; i++) {
10 if (s[i] >= 'a' && s[i] <= 'z') {
11 s[i] = s[i] - 32;
12 } else if (s[i] >= 'A' && s[i] <= 'Z') {
13 s[i] = s[i] + 32;
14 }
15 }
16 cout << s << endl;
17 return 0;
18 }
```
假设输入仅包含英文字母,完成下面的判断题和单选题:
**判断题**
11. 程序执行后,字符串 `s` 的长度可能会发生改变。( )
12. 输入 "CSP" 时,输出 "csp"。( )
13. 该程序实现了大小写字母互换的功能。( )
**单选题**
14. 当输入 "Hello" 时,输出为( )。
A. hello B. HELLO C. hELLO D. Hello
15. 已知 'a' 的 ASCII 码是 97,'A' 的 ASCII 码是 65,则第 11 行可以改为 `s[i] = s[i] - 'a' + 'A'`,效果不变。该说法( )。
A. 正确 B. 错误 C. 编译错误 D. 运行时错误
**(4)**
```cpp
01 #include <iostream>
02 using namespace std;
03
04 int f(int n) {
05 if (n <= 1) return 1;
06 if (n % 2 == 0)
07 return f(n / 2) + n;
08 else
09 return f(n - 1) + 1;
10 }
11
12 int main() {
13 int x;
14 cin >> x;
15 cout << f(x) << endl;
16 return 0;
17 }
```
假设输入的 x 为不超过 1000 的正整数,完成下面的判断题和单选题:
**判断题**
1. 当输入 x 为偶数时,函数 `f(x)` 只会进行递归调用,不会增加数值。( )
2. 该函数一定会终止,不会出现死循环。( )
3. 当输入 5 时,输出结果为 6。( )
**单选题**
4. 当输入 8 时,输出为( )。
A. 13 B. 14 C. 15 D. 16
5. 当输入 10 时,函数 `f` 被调用的次数(包括 `main` 中的第一次调用)是( )。
A. 4 B. 5 C. 6 D. 7
**(5)**
```cpp
01 #include <iostream>
02 using namespace std;
03
04 int main() {
05 int n, m;
06 cin >> n >> m;
07 int a[20][20];
08 for (int i = 0; i < n; i++) {
09 for (int j = 0; j < m; j++) {
10 if (i == 0 || j == 0)
11 a[i][j] = 1;
12 else
13 a[i][j] = a[i - 1][j] + a[i][j - 1];
14 }
15 }
16 cout << a[n - 1][m - 1] << endl;
17 return 0;
18 }
```
假设输入的 n, m 均为不超过 15 的正整数,完成下面的判断题和单选题:
**判断题**
1. 该程序计算的是组合数学中杨辉三角或类似路径计数的问题。( )
2. 如果输入 n=1, m=5,输出结果为 5。( )
3. 无论输入什么正整数,数组 `a` 中的值都会随 `i` 和 `j` 的增大而单调递增(不考虑边界)。( )
**单选题**
4. 当输入 3 3 时,输出为( )。
A. 4 B. 5 C. 6 D. 10
5. 该程序模拟的计算过程等价于求解从网格左上角 (0,0) 走到右下角 (n-1, m-1) 的路径数,且每次只能向右或向下走。如果输入 4 3,输出结果为( )。
A. 6 B. 10 C. 15 D. 20
---
## 三、完善程序 (单选题)
### (1) 判断回文数
读入一个正整数 `n`,判断它是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都一样的整数,例如 121 是回文数,而 123 不是。
```cpp
01 #include <iostream>
02 using namespace std;
03
04 int main() {
05 int n, t, y = 0;
06 cin >> n;
07 t = ①;
08 while (t > 0) {
09 y = y * 10 + ②;
10 t = ③;
11 }
12 if (④)
13 cout << "Yes" << endl;
14 else
15 cout << "No" << endl;
16 return 0;
17 }
```
16. ①处应填( )
A. 0 B. 1 C. n D. -1
17. ②处应填( )
A. t / 10 B. t % 10 C. n % 10 D. n / 10
18. ③处应填( )
A. t / 10 B. t % 10 C. t - 1 D. t + 1
19. ④处应填( )
A. n == t B. n == 0 C. n == y D. y == t
20. 如果输入的 `n` 是 `100`,循环结束后 `y` 的值是( )
A. 1 B. 0 C. 001 D. 10
### (2) 最大公约数与最小公倍数
输入两个正整数 `m` 和 `n`,求它们的最大公约数 (GCD) 和最小公倍数 (LCM)。程序使用辗转相除法(欧几里得算法)的迭代实现。
```cpp
01 #include <iostream>
02 using namespace std;
03
04 int main() {
05 int m, n, a, b, r;
06 cin >> m >> n;
07 a = m;
08 b = n;
09 while (①) {
10 r = m % n;
11 m = ②;
12 n = ③;
13 }
14 cout << "GCD: " << ④ << endl;
15 cout << "LCM: " << ⑤ << endl;
16 return 0;
17 }
```
21. ①处应填( )
A. m != 0 B. n != 0 C. r != 0 D. m % n == 0
22. ②处应填( )
A. n B. r C. a D. b
23. ③处应填( )
A. m B. r C. a D. b
24. ④处应填( )
A. n B. r C. m D. a
25. ⑤处应填( )
A. a * b / m B. a * b / n C. a * b / r D. m * n / a
---
**(3) 高精度加法**
输入两个正整数(可能非常大,超过 `long long` 范围),输出它们的和。
程序使用字符串读取输入,然后转化为数组进行逐位计算。
```cpp
01 #include <iostream>
02 #include <string>
03 #include <algorithm>
04 using namespace std;
05
06 int a[505], b[505], c[505];
07
08 int main() {
09 string s1, s2;
10 cin >> s1 >> s2;
11 int len1 = s1.length();
12 int len2 = s2.length();
13
14 for (int i = 0; i < len1; i++) a[len1 - 1 - i] = ①;
15 for (int i = 0; i < len2; i++) b[len2 - 1 - i] = s2[i] - '0';
16
17 int len = len1 > len2 ? len1 : len2;
18 for (int i = 0; i < len; i++) {
19 c[i] += a[i] + b[i];
20 c[i + 1] = ②;
21 c[i] = ③;
22 }
23
24 if (④) len++;
25
26 for (int i = len - 1; i >= 0; i--) {
27 cout << ⑤;
28 }
29 cout << endl;
30 return 0;
31 }
```
26. ①处应填( )
A. `s1[i]` B. `s1[i] - '0'` C. `s1[len1 - 1 - i]` D. `s1[len1 - 1 - i] - '0'`
27. ②处应填( )
A. `c[i] % 10` B. `c[i] / 10` C. `c[i+1] + c[i] / 10` D. `a[i] + b[i]`
28. ③处应填( )
A. `c[i] / 10` B. `c[i] % 10` C. `a[i] % 10` D. `b[i] % 10`
29. ④处应填( )
A. `c[len] > 0` B. `c[len] >= 10` C. `c[len-1] > 0` D. `c[len] != 0`
30. ⑤处应填( )
A. `c[i]` B. `c[len - i]` C. `a[i] + b[i]` D. `c[i] + '0'`
# 答案与解析
## 阅读程序
### (1)
1. **×**
**解析:** 程序在循环中每次将 `ans` 乘以 `x` 后立即对 10 取模,因此它计算的是 的**个位数字**,而不是 的值。
2. **√**
**解析:** 由于每次运算都执行 `% 10`,结果 `ans` 必定在 0 到 9 之间。
3. **√**
**解析:** 输入 2 3,循环执行 3 次。
```
i=1: ans = 1*2%10 = 2
i=2: ans = 2*2%10 = 4
i=3: ans = 4*2%10 = 8
输出 8。
```
4. **B**
**解析:** 输入 12 2。
```
i=1: ans = 1*12%10 = 12%10 = 2
i=2: ans = 2*12%10 = 24%10 = 4
输出 4。
```
5. **B**
**解析:** 输入 2 10,计算 的个位数。 规律为 2,4,8,6 循环。10 % 4 = 2,所以是第 2 个,即 4。
### (2)
6. **×**
**解析:** 变量 `count` 累加的是 `a[i]` 的值(`count = count + a[i]`),而不是个数。它计算的是**大于0的偶数之和**。
7. **√**
**解析:** 如果全是负数,`a[i] > 0` 条件始终不满足,`count` 保持初始值 0。
8. **×**
**解析:** 如果去掉 `a[i] > 0`,负偶数也会被加进去,结果会改变。例如输入 -2,原程序加 0,去掉条件后加 -2。
9. **C**
**解析:** 数组 1 2 3 4 5 中,大于0的偶数有 2, 4。和为 2+4=6。
10. **A**
**解析:** 数组 -2 -4 2 4 6 中,大于0的偶数有 2, 4, 6。和为 2+4+6=12。
### (3)
11. **×**
**解析:** 程序只是修改字符的值(ASCII码变换),不涉及插入或删除,长度不变。
12. **√**
**解析:** C, S, P 都是大写,满足第二个 `if`,加 32 变为小写 c, s, p。
13. **√**
**解析:** 第一个 `if` 将小写转大写(-32),第二个 `if` 将大写转小写(+32)。
14. **C**
**解析:** "Hello"。'H' 是大写 -> 'h'。'e','l','l','o' 是小写 -> 'E','L','L','O'。输出 "hELLO"。
15. **A**
**解析:** `s[i] - 32` 等价于 `s[i] - ('a' - 'A')`,即 `s[i] - 'a' + 'A'`。这是标准的转换方式。
## 完善程序
### (1) 判断回文数
* **算法思路:** 将数字 `n` 翻转生成新数字 `y`,比较 `n` 和 `y` 是否相等。
* **解析:**
16. **C (n)**:需要用一个临时变量 `t` 来操作,保留原数 `n` 用于最后比较,所以 `t` 初始化为 `n`。
17. **B (t % 10)**:取出 `t` 的最后一位数字。
18. **A (t / 10)**:去掉 `t` 的最后一位数字,以便下一次循环取下一位。
19. **C (n == y)**:比较原数 `n` 和翻转后的数 `y`。
20. **A (1)**:`n=100`。
第一次:`y=0+0=0`, `t=10`
第二次:`y=0+0=0`, `t=1`
第三次:`y=0+1=1`, `t=0`
循环结束,`y` 为 1。
### (2) 最大公约数与最小公倍数
* **算法思路:** 欧几里得算法:`gcd(m, n) = gcd(n, m % n)`,直到 `n` 为 0,此时 `m` 即为 GCD。LCM = (a * b) / GCD。
* **解析:**
21. **B (n != 0)**:循环继续的条件是除数不为 0。
22. **A (n)**:将原来的除数 `n` 赋值给被除数 `m`。
23. **B (r)**:将余数 `r` 赋值给除数 `n`。
24. **C (m)**:循环结束时 `n` 为 0,`m` 存储的是最大公约数。
25. **A (a * b / m)**:最小公倍数 = 两数之积 / 最大公约数。注意原数保存在 `a` 和 `b` 中,`m` 是计算出的 GCD。
Loaded 100 of 1789 files, more files were not shown because too many files have changed in this diff. Show more