🔐 C3-10 拓展解析
15道OJ题 + 5道代码填空 · 题目内容/解题思路/完整代码/易错点/家长辅导建议
📋 目录
1. L57 密码破解(入门)
📝 题目内容
已知一段加密的小写字母字符串,加密规则是每个字母向后移了k位。请解密得到原始字符串。
💡 解题思路
- 读入加密字符串和k
- 每个字符反向移位:减去k
- 用 (c-'a'-k+26)%26+'a' 防止负数绕回
💻 完整代码
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
int k;
cin >> s >> k;
for(int i = 0; i < s.length(); i++) {
// ★ 解密:反向移k位,+26防止负数
s[i] = (s[i] - 'a' - k + 26) % 26 + 'a';
}
cout << s << endl;
return 0;
}
⚠️ 易错点:减k可能变负数,一定要+26再%26!
👨👩👧 家长辅导:让孩子先手动加密再解密,理解"加k加密、减k解密"的对称关系。
2. L151 鸡兔同笼问题(入门)
📝 题目内容
已知鸡兔总头数n和总脚数m,求鸡和兔各有多少只。
💡 解题思路
- 枚举鸡的数量i从0到n
- 兔子数量 = n - i
- 检查 2*i + 4*(n-i) == m
💻 完整代码
#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
for(int chicken = 0; chicken <= n; chicken++) {
int rabbit = n - chicken;
// ★ 检查总脚数
if(2*chicken + 4*rabbit == m) {
cout << chicken << " " << rabbit << endl;
}
}
return 0;
}
⚠️ 易错点:鸡2只脚、兔4只脚,别搞混!
👨👩👧 家长辅导:这是中国古代数学名题,可画图帮孩子理解头和脚的关系。
3. L237 找数组的最大数(入门)
📝 题目内容
输入n个整数,输出其中的最大值。
💡 解题思路
- 打擂台法:先假设第一个最大
- 遍历数组,遇到更大的就更新
💻 完整代码
#include <iostream>
using namespace std;
int main() {
int n, a[100];
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
int maxV = a[0]; // ★ 先设第一个为擂主
for(int i = 1; i < n; i++) {
if(a[i] > maxV) maxV = a[i]; // ★ 更大就换擂主
}
cout << maxV << endl;
return 0;
}
⚠️ 易错点:maxV初始值不要设为0,否则全负数会出错。
👨👩👧 家长辅导:用"打擂台"比喻——先派第一个人上台,后面每个人挑战,赢了就当新擂主。
4. L244 陶陶摘苹果(入门)
📝 题目内容
10个苹果挂在不同高度,陶陶站在凳子上伸手高度为h,问能摘到几个苹果。
💡 解题思路
- 读入10个苹果高度
- 读入伸手高度h(含凳子30cm)
- 统计高度 <= h 的苹果数
💻 完整代码
#include <iostream>
using namespace std;
int main() {
int a[10], h, cnt = 0;
for(int i = 0; i < 10; i++) cin >> a[i];
cin >> h;
for(int i = 0; i < 10; i++) {
if(a[i] <= h) cnt++; // ★ 够得到就计数
}
cout << cnt << endl;
return 0;
}
⚠️ 易错点:是<=(够得到),不是<!
👨👩👧 家长辅导:NOIP经典题,让孩子理解"够得到"就是苹果高度不超过伸手高度。
5. L239 查找含有x的数(入门)
📝 题目内容
输入n个数和x,查找x在数组中的位置,找到输出下标,没找到输出-1。
💡 解题思路
- 顺序查找:遍历数组逐个比较
- 找到就输出下标并break
- 循环结束都没找到就输出-1
💻 完整代码
#include <iostream>
using namespace std;
int main() {
int n, a[100], x, pos = -1;
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
cin >> x;
for(int i = 0; i < n; i++) {
if(a[i] == x) { // ★ 找到了
pos = i;
break; // ★ 找到就退出
}
}
cout << pos << endl;
return 0;
}
⚠️ 易错点:下标从0开始!题目如果要求从1开始要+1。
👨👩👧 家长辅导:顺序查找就像翻书找名字,一页一页翻,找到了就停下。
6. L246 人数统计(入门)
📝 题目内容
输入n个成绩和分数线,统计大于等于分数线的人数。
💡 解题思路
- 读入n和分数线line
- 遍历成绩,>=line就计数+1
💻 完整代码
#include <iostream>
using namespace std;
int main() {
int n, line, score, cnt = 0;
cin >> n >> line;
for(int i = 0; i < n; i++) {
cin >> score;
if(score >= line) cnt++; // ★ 及格线判断
}
cout << cnt << endl;
return 0;
}
⚠️ 易错点:题目说"大于等于"就是>=,不是>!
👨👩👧 家长辅导:联系生活——考试及格人数统计,让孩子理解>=和>的区别。
7. L256 去除重复数字(入门)
📝 题目内容
输入n个数,去掉重复的,只保留第一次出现的,按原顺序输出。
💡 解题思路
- 双重循环:对每个a[i],检查它前面有没有出现过
- 前面没有出现过 = 第一次出现 → 输出
💻 完整代码
#include <iostream>
using namespace std;
int main() {
int n, a[100];
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
for(int i = 0; i < n; i++) {
bool seen = false;
for(int j = 0; j < i; j++) {
if(a[j] == a[i]) { seen = true; break; } // ★ 前面出现过
}
if(!seen) cout << a[i] << " "; // ★ 第一次出现才输出
}
return 0;
}
⚠️ 易错点:双重循环别漏了break,否则seen判断会出错。
👨👩👧 家长辅导:去重就像点名——如果之前已经点过这个名字,就跳过不点。
8. L260 出现次数最多的数(入门)
📝 题目内容
输入n个数,找出出现次数最多的数。次数相同取较小的。
💡 解题思路
- 桶计数:用cnt数组统计每个数出现几次
- 遍历cnt找最大次数对应的数
💻 完整代码
#include <iostream>
using namespace std;
int main() {
int n, x, cnt[1001] = {0};
cin >> n;
for(int i = 0; i < n; i++) {
cin >> x;
cnt[x]++; // ★ 桶计数
}
int maxCnt = 0, ans = 0;
for(int i = 1; i <= 1000; i++) {
if(cnt[i] > maxCnt) { // ★ 次数更多就更新
maxCnt = cnt[i];
ans = i;
}
}
cout << ans << endl;
return 0;
}
⚠️ 易错点:相同次数取较小数,所以用>不是>=(先遇到的小数保留)。
👨👩👧 家长辅导:桶计数就像投票——每个数字一票,票数最多的数字当选。
9. T1051 分段函数(入门)
📝 题目内容
定义分段函数f(x),根据x的不同范围返回不同值,主函数调用并输出。
💡 解题思路
- 定义函数f(x),内部用if-else分段
- 主函数读入x,调用f(x)输出
💻 完整代码
#include <iostream>
using namespace std;
int f(int x) {
if(x < 0) return -x; // ★ x负返回-x
else if(x < 10) return x*x; // ★ 0~9返回平方
else return 2*x; // ★ >=10返回2x
}
int main() {
int x;
cin >> x;
cout << f(x) << endl;
return 0;
}
⚠️ 易错点:分段条件要互斥且完整,别漏掉边界。
👨👩👧 家长辅导:函数就像一个"机器",输入x,经过内部规则加工,输出结果。
10. L247 数组元素的排序(入门)
📝 题目内容
输入n个数,将它们从小到大排序后输出。
💡 解题思路
- 读入数组
- 用sort(a, a+n)升序排序
- 遍历输出
💻 完整代码
#include <iostream>
#include <algorithm> // ★ sort需要这个头文件
using namespace std;
int main() {
int n, a[100];
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
sort(a, a + n); // ★ 升序排序
for(int i = 0; i < n; i++) cout << a[i] << " ";
return 0;
}
⚠️ 易错点:忘了#include <algorithm>会编译错误!
👨👩👧 家长辅导:sort就像自动排队——告诉它队伍从哪开始到哪结束,它自动帮你排好。
11. G1021 [GESP202406三级] 移位-T1(普及-)
📝 题目内容
GESP三级真题。输入小写字符串和k,每个字母向后移k位加密。
💡 解题思路
- k可能大于26,先k%=26
- 每个字母用(c-'a'+k)%26+'a'移位
💻 完整代码
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
int k;
cin >> s >> k;
k = k % 26; // ★ 超过26圈数没意义
for(int i = 0; i < s.length(); i++) {
s[i] = (s[i] - 'a' + k) % 26 + 'a'; // ★ 循环移位
}
cout << s << endl;
return 0;
}
⚠️ 易错点:k可能很大(如k=30),先%26简化。
👨👩👧 家长辅导:这是GESP三级真题,让孩子熟悉考试题型和格式要求。
12. G1134 [GESP真题] 凯撒密码(普及)
📝 题目内容
经典凯撒密码加密。输入明文字符串和移位量,输出密文。
💡 解题思路
- 遍历每个字符
- 小写字母用%26,大写字母也要处理
- 非字母字符保持不变
💻 完整代码
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
int k;
getline(cin, s);
cin >> k;
k = k % 26;
for(int i = 0; i < s.length(); i++) {
if(s[i] >= 'a' && s[i] <= 'z') {
s[i] = (s[i] - 'a' + k) % 26 + 'a'; // ★ 小写
} else if(s[i] >= 'A' && s[i] <= 'Z') {
s[i] = (s[i] - 'A' + k) % 26 + 'A'; // ★ 大写
}
}
cout << s << endl;
return 0;
}
⚠️ 易错点:要判断是大写还是小写,分别处理!空格等非字母字符不变。
👨👩👧 家长辅导:这个题难度稍高,需要区分大小写,让孩子先从小写版本练熟。
13. T1370 最小函数值(普及-)
📝 题目内容
已知二次函数f(x)=ax²+bx+c,枚举x=1~n,求f(x)的最小值。
💡 解题思路
- 定义函数f(x)=a*x*x+b*x+c
- 枚举x从1到n,打擂台找最小值
- 注意用long long防止溢出
💻 完整代码
#include <iostream>
using namespace std;
long long f(long long a, long long b, long long c, long long x) {
return a*x*x + b*x + c; // ★ 二次函数
}
int main() {
long long a, b, c, n;
cin >> a >> b >> c >> n;
long long minV = f(a,b,c,1);
for(long long x = 2; x <= n; x++) {
long long val = f(a,b,c,x);
if(val < minV) minV = val; // ★ 打擂台找最小
}
cout << minV << endl;
return 0;
}
⚠️ 易错点:x²可能很大,一定要用long long!
👨👩👧 家长辅导:这个题结合了函数封装和枚举,是很好的综合练习。
14. L250 第K大与第K小数(普及-)
📝 题目内容
输入n个数,求第K小和第K大的数。
💡 解题思路
- sort升序排序
- 第K小 = a[K-1](下标从0开始)
- 第K大 = a[n-K]
💻 完整代码
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n, k, a[100];
cin >> n >> k;
for(int i = 0; i < n; i++) cin >> a[i];
sort(a, a + n); // ★ 升序
cout << a[k-1] << endl; // ★ 第K小
cout << a[n-k] << endl; // ★ 第K大
return 0;
}
⚠️ 易错点:下标从0开始!第1小是a[0],第n小是a[n-1]。
👨👩👧 家长辅导:排队类比——从小到大排好队,第K个小个子就是第K小。
15. L261 缺失的数字(普及-)
📝 题目内容
1到n中缺少了一个数,给你n-1个数,找出缺失的那个。
💡 解题思路
- 方法一:标记法,用bool数组标记出现过的数
- 方法二:求和法,1到n的和减去已有数之和
💻 完整代码(求和法)
#include <iostream>
using namespace std;
int main() {
int n, x, sum = 0;
cin >> n;
for(int i = 0; i < n-1; i++) {
cin >> x;
sum += x; // ★ 累加已有数
}
int total = n * (n + 1) / 2; // ★ 1到n的总和
cout << total - sum << endl; // ★ 差值就是缺失的
return 0;
}
⚠️ 易错点:输入的是n-1个数,不是n个!循环次数别错。
👨👩👧 家长辅导:求和法很巧妙——应该有的总和减去实际有的总和,差的就是丢的那个。