外观
2026-计算概论C-py作业4
题集链接
OpenJudge/计算概论C(py)/2026-计算概论C-py作业4共 5 题。题面、知识点、解题提示和易错点可直接查看;完整参考解析于北京时间 2026-10-27 13:00 截止后公开,教师可用作业 2 的密码提前查看。
01:数列求和
题目描述
对数列进行求和。给定一个整数 n,当 n 为偶数时,计算 1/2 + 1/4 + ...... + 1/n 的和;当 n 为奇数时,计算 1/1 + 1/3 + ...... + 1/n 的和。
要求使用函数实现。
输入
一个整数 n (0 < n <= 1000)
输出
一个浮点数表示数列的和,保留 6 位小数
样例输入
text
# 样例 1
8
# 样例 2
9样例输出
text
# 样例 1
1.041667
# 样例 2
1.787302样例中的 # 样例 为分组标签,每组需独立运行,标签本身不属于输入。
解题提示
本题知识点: 第 2 章《基本数据类型》: 用 / 计算倒数,用 f 字符串控制小数位数;第 3 章《程序控制结构与异常处理》: range() 的起点、终点与步长,循环累加;第 4 章《函数》: 定义函数、传入参数、用 return 返回结果。
- 先列出需要哪些分母:
n=8时是2、4、6、8,n=9时是1、3、5、7、9。每项都是“1 除以当前分母”,相邻分母相差 2。 - 把求和过程写入函数。函数接收
n,在内部初始化累计值,逐项相加,最后把总和返回给调用处。 - 主程序负责读入整数、调用函数和输出;只在最后输出时保留 6 位小数。
分母关键点:先确定循环会取到哪些数。 range(start, stop, step) 包含起点、不包含终点,第三个参数表示每次增加多少。例如:
python
list(range(2, 9, 2)) # [2, 4, 6, 8]
list(range(1, 10, 2)) # [1, 3, 5, 7, 9]这里 list() 只是为了观察 range() 生成的数,正式求和时直接用 for 遍历即可。以下两种分母遍历方式任选一种。
方法一:按奇偶性确定起点,正向遍历
偶数从 2 开始,奇数从 1 开始;因为需要包含 n,终点写成 n + 1。
python
if n % 2 == 0:
start = 2
else:
start = 1
# range(start, n + 1, 2) 给出本题需要的全部分母例如 n=8,依次取到 2、4、6、8;下一项 10 已超过终点,循环结束。
方法二:从 n 开始,每次减 2
与 n 同奇偶的数减去 2 后仍保持奇偶性,因此也可以从后往前取分母:
python
list(range(8, 0, -2)) # [8, 6, 4, 2]
list(range(9, 0, -2)) # [9, 7, 5, 3, 1]终点 0 不会被取到,既能保留最后的 1 或 2,也能避免除以零。这种方式不用另写奇偶分支。
累加关键点:每轮保留之前的结果,再加上当前一项。 假设当前分母是 denominator:
python
total += 1 / denominator这相当于 total = total + 1 / denominator。以 n=6、正向遍历为例:
| 当前分母 | 本轮增加 | 累计值 |
|---|---|---|
| 尚未开始 | — | 0 |
| 2 | 1 / 2 | 0.5 |
| 4 | 1 / 4 | 0.75 |
| 6 | 1 / 6 | 约 0.9166667 |
total 应在循环开始前初始化一次。如果每轮都重新赋值为 0,之前加过的数就丢失了。
函数关键点:return 把结果交回调用处。 可以按下面的框架组织,补全中间的求和过程:
python
def seriesSum(n):
total = 0.0
# 在这里遍历分母,把每项累加到 total
return totalreturn total 与循环语句处于同一级缩进,应在所有项加完后执行。若缩进到循环内部,第一次累加后函数就结束了。函数中只 print(total) 而不 return,调用者拿到的会是 None。
输出格式可单独练习:f'{0.5:.6f}' 得到字符串 0.500000。这与 round(0.5, 6) 得到数值 0.5 不同;本题要求显示足够的小数位。
易错点
- 漏掉最后一项:
range(start, n, 2)不包含n;正向遍历时应检查终点设置。 - 把除法写成整除:
1 // denominator会舍去小数部分;这里需要/。 - 累加量反复清零: 初始化在循环外;每轮使用累加,不能直接用当前一项覆盖总和。
- 提前返回或只打印不返回: 检查
return的缩进,以及主程序接收到的是否为数值。 - 过早舍入: 不要每算一项就保留 6 位小数,累计误差可能改变最后结果;统一在输出时格式化。
可用 n=1 → 1.000000、n=2 → 0.500000、n=6 → 0.916667 自测,再检查题面两组样例。
本题答案暂未公开
北京时间 2026/10/27 13:00:00 解锁
正在检查解锁状态…
正在载入加密答案…
02:删除子串
题目描述
有两个非空字符串,一个长的字符串,一个短的字符串。现在要在长串中查找并删除短串,打印处理后的结果。一个额外的参数表示全部删除子串或者至多删除一次。查找时从左到右查找,找到的子串不允许重叠(参见样例3)。
要求使用函数实现。
输入
输入只有一行,共三项,用空格隔开。前两个是字符串,分别是长字符串和短字符串。前者长度大于等于后者的长度,且字符串中不包含空白符。还有一个整数 n,取值为 0 或 1,0 表示至多删除一次,1 表示全部删除。
输出
如果短串包含在长串中,则打印处理后的字符串,否则打印 "Fail to delete"
样例输入
text
# 样例 1
abcdeabcde fg 0
# 样例 2
abcdeabcde ab 1
# 样例 3
aaababbaaa aa 1样例输出
text
# 样例 1
Fail to delete
# 样例 2
cdecde
# 样例 3
ababba样例中的 # 样例 为分组标签,每组需独立运行,标签本身不属于输入。
解题提示
本题知识点: 第 2 章《基本数据类型》: split() 拆分输入、in 判断子串、replace() 替换字符串;第 3 章《程序控制结构与异常处理》: 先判断是否存在,再按模式分支;第 4 章《函数》: 接收多个参数并返回字符串。
- 三项数据在同一行:前两项保留为字符串,第三项转成整数。不要对长串、短串进行数值转换。
- 先判断短串是否在原长串中。没有出现时返回题目指定的
Fail to delete;出现时再判断删除模式。 - 模式 0 只处理最左边的一次匹配,模式 1 处理全部不重叠匹配。把处理后的字符串作为函数返回值,由主程序统一输出。
输入关键点:只转换模式。
python
long_str, short_str, mode = input().split()
mode = int(mode)函数可以接收这三个值,例如定义成 strFindDel(long_str, short_str, mode)。函数返回的无论是处理结果还是失败提示,都是字符串。
删除关键点:用空字符串替换子串。 s.replace(old, new, count) 的含义是:在 s 中把 old 换成 new,最多替换 count 次;省略第三个参数时替换全部不重叠匹配。
用一个小例子观察各参数的作用:
python
text = "ab12ab"
text.replace("ab", "X", 1) # "X12ab":只替换最左边一次
text.replace("ab", "", 1) # "12ab":用空串替换,即删除一次
text.replace("ab", "") # "12":删除全部不重叠匹配这些表达式返回新字符串,不会改变原变量 text。要保存结果,就赋值给变量;要把结果交给调用者,就使用 return。
| 输入模式 | 题目含义 | 对应的替换次数 |
|---|---|---|
0 | 至多删除一次 | 第三个参数为 1 |
1 | 删除全部 | 省略第三个参数 |
因此,模式的值不是替换次数。如果直接把 mode 作为第三个参数,模式 0 会变成“一次也不替换”,模式 1 又会变成“只替换一次”。
不重叠关键点:按原串从左到右扫描,匹配过的字符不再重复使用。 这与作业 3 的“找出全部子串位置”采用同样的跳过规则。
样例 aaababbaaa 可以按扫描结果分成:
text
[aa] + ababb + [aa] + a删除方括号内的两段,剩下 ababb + a,即 ababba。不能把前三个 a 中相互重叠的两个 aa 都删除。
还要区分“删除原串中的全部匹配”和“删到再也找不到为止”:
text
原串:a + [aba] + ba
删除原有匹配后:aba对于 aababa 删除 aba,结果仍是 aba。留下的这个 aba 是删除后拼接形成的,不应重新从头继续删除。直接用一次 replace() 符合题意;反复 while short_str in result 会把结果错误地删空。
失败与空结果不同: abc 中删除 abc 是成功删除,结果为空串,应输出一个空行;abc 中查找 z 才属于失败。因此是否失败应在删除前根据原串判断,不能用结果是否为空来判断。
易错点
- 模式与次数混淆: 模式 0 对应删除一次,模式 1 对应删除全部,需先分支再调用替换方法。
- 没有接住新字符串: 单独调用
s.replace(...)后继续输出s,会仍然输出原串。 - 反复删除新形成的子串: 本题只对原串从左向右做不重叠匹配;用
aababa aba 1检查,结果应为aba。 - 把空串当作失败:
abc abc 0应输出空行,不能输出Fail to delete。 - 失败文字不一致: 大小写、单词间空格都需保持
Fail to delete;不要增加引号或中文说明。
可补测 aaaa aa 0 → aa、aaaa aa 1 → 空串、aaa aa 1 → a,对照一次删除、全部删除和不重叠规则。
本题答案暂未公开
北京时间 2026/10/27 13:00:00 解锁
正在检查解锁状态…
正在载入加密答案…
03:机器猜数
题目描述
随机选择 1 ~100 的一个整数 n,通过某种规则判断这个数 n 是多少。
规则如下:给定当前的数字范围[a, b],选择其中间的数 m=(a+b)/2,判断 m 和 n 的大小关系。如果 m = n,则表示猜对了,如果 m > n,则在 [a, m-1] 中继续判断,如果 m < n,则在 [m+1, b] 中继续判断。如果数字范围 [a, b] 的中间数 m 不是整数,则向上取整,例如 [1, 4],则 m = 3。如果数字范围满足 a = b,那么数 n 一定满足 n = a = b,此时不需要继续猜数。
初始的数字范围是 [1, 100]。现在有一个猜数机器,按照上述的规则进行猜数,那么这个猜数机器需要猜几次?
输入
一个整数,范围是 1 ~ 100(包含1和100)
输出
一个整数,表示按照题目的规则猜数,猜对结果时总共猜数的次数。
样例输入
text
# 样例 1
5样例输出
text
# 样例 1
6样例中的 # 样例 为分组标签,每组需独立运行,标签本身不属于输入。
解题提示
本题知识点: 第 2 章《基本数据类型》: 整除与向上取整;第 3 章《程序控制结构与异常处理》: while 循环、条件分支、计数和 break。本题使用“每次排除一半候选数”的二分思路。
- 维护两个变量
left、right,表示当前仍可能包含目标的范围,初始为 1 和 100;另设计数器,初始为 0。 - 只要范围内仍有至少两个候选数,就取中点猜一次,并把次数加一。中点必须按题意向上取整。
- 比较中点与目标:相等就停止;猜大了保留左侧,猜小了保留右侧。两种情况下都要排除本轮已经猜过的中点。
- 如果范围只剩一个数,可以直接确定目标,不再猜一次,也不再增加计数。
中点关键点:普通的整除会向下取整。 本题的端点都是整数,可以用“先加 1,再整除 2”得到向上取整的平均值:
python
middle = (left + right + 1) // 2| 当前范围 | 平均值 | 本题应猜 | (left + right) // 2 会得到 |
|---|---|---|---|
[1, 100] | 50.5 | 51 | 50 |
[1, 4] | 2.5 | 3 | 2 |
[1, 5] | 3 | 3 | 3 |
端点和为奇数时,加 1 能补足半个整数;端点和为偶数时,加 1 后再整除仍得到原来的整数平均值。也可用 math.ceil((left + right) / 2);不要用 round() 代替向上取整。
区间更新关键点:已经猜过的中点不再保留。
| 比较结果 | 下一步 | 原因 |
|---|---|---|
middle == n | 本轮计数后结束 | 已猜中 |
middle > n | right = middle - 1 | 目标严格小于中点 |
middle < n | left = middle + 1 | 目标严格大于中点 |
不能只写 left = middle 或 right = middle:这会把已经排除的数继续留在范围里,有时还会让范围无法缩小。
计数关键点:猜中和“只剩一个候选数”是两种结束方式。 用样例 n=5 逐轮检查:
| 第几次猜测 | 猜测前的范围 | 向上取整的中点 | 与 5 比较 | 下一范围 |
|---|---|---|---|---|
| 1 | [1, 100] | 51 | 猜大了 | [1, 50] |
| 2 | [1, 50] | 26 | 猜大了 | [1, 25] |
| 3 | [1, 25] | 13 | 猜大了 | [1, 12] |
| 4 | [1, 12] | 7 | 猜大了 | [1, 6] |
| 5 | [1, 6] | 4 | 猜小了 | [5, 6] |
| 6 | [5, 6] | 6 | 猜大了 | [5, 5] |
最后虽然没有把中点猜成 5,但范围已是 [5,5],可以直接确定目标,所以答案是 6 次。若写成 while left <= right,就容易在最后多猜一次;本题应只在 left < right 时继续猜。
另一方面,n=51 第一次就猜中,答案是 1,不能因为相等就先退出、漏记本轮。安排语句时可按“计算中点 → 次数加一 → 比较并更新”的顺序。
易错点
- 使用向下取整的中点: 第一次必须猜 51;猜 50 就已经偏离题目规则。
- 把单元素区间也算一次:
[5,5]无需猜测,计数不会再增加。 - 猜中这一轮没有计数: 次数加一应在退出前完成;用
n=51检查。 - 更新方向颠倒: 猜大了缩小右端点,猜小了增大左端点,且都排除中点。
- 把“随机选择”理解为随机生成: 目标数由输入提供,不需要
random;程序模拟的是给定规则。
除样例外,可检查 n=26 → 2、n=1 → 6、n=100 → 6,覆盖提前猜中及范围两端。
本题答案暂未公开
北京时间 2026/10/27 13:00:00 解锁
正在检查解锁状态…
正在载入加密答案…
04:自动判题
题目描述
自动判断一个简单的数学等式是否成立。这里的数学等式是两个数的四则运算(加,减,乘,除)。参与运算的数是浮点数,结果保留两位小数。
输入
一个等式。数字和运算符之间没有空格。等式左边的两个数是非负数,右边的结果仅仅保留两位小数。
输出
一个字符串,true 或者 false
样例输入
text
# 样例 1
2.1*4=8.40
# 样例 2
1/3=0.33
# 样例 3
1.57-5.33=-1.51样例输出
text
# 样例 1
true
# 样例 2
true
# 样例 3
false样例中的 # 样例 为分组标签,每组需独立运行,标签本身不属于输入。
解题提示
本题知识点: 第 2 章《基本数据类型》: split() 拆分字符串、float() 转换数字、round() 保留小数位;第 3 章《程序控制结构与异常处理》: 根据运算符选择分支、根据比较结果输出指定字符串。
- 先把一行沿等号分成“待计算的表达式”和“给定结果”。给定结果只需转成数值;左侧还要拆出两个操作数和运算符。
- 题目保证左侧两个数非负,可以在左侧依次检查
+、-、*、/,找到运算符后按它拆分。 - 将两个操作数转成浮点数,按运算符执行计算。再将计算值保留两位小数,与右侧的数值比较。
- 比较成立时输出小写
true,不成立时输出小写false。
拆分关键点:先拆等号,再处理左侧。 可先用固定字符串练习:
python
expression, expected_text = "1.57-5.33=-1.51".split("=")
# expression 是 "1.57-5.33"
# expected_text 是 "-1.51"右侧结果可能带负号。如果直接对整行按 - 拆分,会把右侧负号也拆掉。先沿等号分开,就能把“左侧减法运算符”和“右侧负数符号”区分开。
对于左侧,可把“查找运算符”单独写成一小段:
python
for operator in "+-*/":
if operator in expression:
left_text, right_text = expression.split(operator)
break找到后,left_text、right_text 仍是字符串,需分别转成 float。这个拆分方法依赖题面“左侧两个数非负”的条件,不能直接套到任意复杂表达式上。
运算关键点:变量里的符号不会自动变成运算。 当 operator 的值为 "*" 时,Python 不会自动把它当作乘号执行;用 if/elif 选择真正的运算。例如加法分支可以写成:
python
if operator == "+":
calculated = left_number + right_number其余三个分支按对应运算补齐即可。此时两侧操作数已经是浮点数,+ 才表示数值相加,而不是字符串拼接。
精度关键点:先保留两位小数,再比较。
| 输入等式 | 左侧计算值 | 保留两位后的数值 | 右侧数值 | 应输出 |
|---|---|---|---|---|
2.1*4=8.40 | 8.4 | 8.4 | 8.4 | true |
1/3=0.33 | 约 0.333333… | 0.33 | 0.33 | true |
1.57-5.33=-1.51 | 约 -3.76 | -3.76 | -1.51 | false |
第一行中的 8.4 和 8.40 表示同一个数。不能直接比较它们的字符串形式,也不能不做小数位处理就比较 1/3 与 0.33。
可以先独立观察这个局部过程:
python
rounded_value = round(1 / 3, 2) # 0.33
expected_value = float("0.33")参考解法在舍入后用 math.isclose(rounded_value, expected_value) 比较。这一函数返回布尔值,使用前需 import math;最后仍需把布尔判断映射成题目要求的小写单词。
round() 和固定两位小数的格式化有什么区别?
python
round(8.4, 2) # 数值 8.4
f'{8.4:.2f}' # 字符串 "8.40"round() 返回可继续计算和比较的数值;f 字符串控制显示形式,返回字符串。本题最终只输出 true 或 false,所以不必把中间计算值输出成两位小数。
Python 的 round() 在恰好位于中间的情况采用向偶数舍入,例如 round(0.125, 2) 为 0.12;浮点数本身也可能存在表示误差。不要自行给所有结果加上 0.005,尤其负数时不能这样处理。
易错点
- 整行按减号拆分: 右侧可能是负数;先拆等号,再找左侧运算符。
- 忘记类型转换:
"2.1" + "4"得到字符串"2.14",不是数值加法。 - 没有先舍入: 直接比较原始计算值,会把
1/3=0.33错判为不成立;math.isclose()也不能替代保留两位小数这一步。 - 把比较变成“差小于一分钱”: 两个不同的两位小数结果不应因为人为放宽容差而被当成相等,例如
2.1*4=8.41应为false。 - 输出布尔值本身:
print(True)输出的是大写开头的True;题目要求小写true、false。
可再用 0.1+0.2=0.30、1-2=-1.00 检查浮点数加法和负结果,两者均应输出 true。
本题答案暂未公开
北京时间 2026/10/27 13:00:00 解锁
正在检查解锁状态…
正在载入加密答案…
05:凯撒密码
题目描述
对字母和数字进行加密和解密。密钥是一个数字,用于加密和解密。
要求使用函数实现。
输入
输入有三行,每行一项,分别是模式、密钥、需要处理的信息。 第一行为模式,可能是 e, E, encrypt, Encrypt (这四个表示加密), d, D, decrypt, Decrypt (这四个表示解密), 或者是其他字符串。 第二行为密钥,是一个大于 0 且小于等于 26 的整数。 第三行为需要处理的信息,是一个字符串。
输出
如果模式表示加密或解密,则输出一个字符串,表示加密信息或解密信息。 如果模式既不是加密或解密,那么不论密钥和需要处理的信息是什么,都输出 "Wrong Mode"。
样例输入
text
e
23
I am a student. My ID is 19123.样例输出
text
F xj x pqrabkq. Jv FA fp 42456.解题提示
本题知识点: 第 2 章《基本数据类型》: ord()、chr()、取余与字符串拼接;第 3 章《程序控制结构与异常处理》: 模式判断、字符分类和逐字符循环;第 4 章《函数》: 把重复的字符转换步骤封装为函数。
- 按三行读取模式、密钥、消息。模式先与题面列出的字符串比较,无效时输出
Wrong Mode;有效时确定是向加密方向移动还是向解密方向移动。 - 逐个处理消息中的字符:大写字母、小写字母、数字分别转换;空格、标点等其他字符原样保留。
- 对需要转换的字符,先算它在所属字符组中的位置,再移动、取余、转换回字符。把这段共用过程写成函数。
- 按原顺序拼接每个转换结果,最后只输出完整消息。
与作业 2 的联系:从“一个小写字母”扩展到“一整行、多种字符和解密”。 作业 2 的字母加密使用 26 个小写字母组成的环;本题需要区分三个独立的环:
| 字符类别 | 范围判断示例 | 起点字符 | 位置范围 | 环的长度 |
|---|---|---|---|---|
| 大写字母 | 'A' <= ch <= 'Z' | 'A' | 0~25 | 26 |
| 小写字母 | 'a' <= ch <= 'z' | 'a' | 0~25 | 26 |
| 数字字符 | '0' <= ch <= '9' | '0' | 0~9 | 10 |
| 其他字符 | 不属于上述三类 | — | — | 原样保留 |
例如 '0' 是字符,0 是整数;ord('0') 得到字符编码,不是整数 0。先减去所在组起点的编码,才能得到从 0 开始的位置。
转换关键点:减起点、移动、取余、加回起点。 以下片段只演示一个小写字符如何绕过末尾:
python
ch = 'z'
base = ord('a')
position = ord(ch) - base # 25
new_position = (position + 3) % 26 # 2
new_char = chr(base + new_position) # 'c'ord() 将字符转成编码;chr() 将编码转回字符。不能直接对 ord(ch) + key 取余后调用 chr(),因为余数是环内位置,还没有加回字符组起点。
解密关键点:沿同一个环向反方向移动。 加密用 +key,解密用 -key,因此可先根据模式把“移动量”设成正数或负数,后续转换过程共用。
以密钥 3 解密小写字母 b 为例:
text
b 的位置为 1
向前退 3 步:1 - 3 = -2
回到 26 个位置的环中:(-2) % 26 = 24
位置 24 对应 yPython 对正整数 26 取余时,结果会落在 0~25,负的移动位置也能自动绕回。无需为越过 'a' 再写一套特殊分支。
| 操作 | 环内计算 | 转换结果 |
|---|---|---|
z 加密,密钥 3 | (25 + 3) % 26 = 2 | c |
b 解密,密钥 3 | (1 - 3) % 26 = 24 | y |
8 加密,密钥 15 | (8 + 15) % 10 = 3 | 3 |
3 解密,密钥 15 | (3 - 15) % 10 = 8 | 8 |
数字一行尤其值得检查:密钥 15 超过数字环长 10,但取余仍能处理;不能对数字也使用 % 26。
函数关键点:把变化的部分作为参数。 三种字符组使用同一种转换过程,区别只是起点和环长。可设计一个接收“字符、移动量、起点字符、环长”的函数:
python
def transform(ch, shift, base_char, cycle_length):
# 求 ch 相对 base_char 的位置
# 移动 shift 步,并对 cycle_length 取余
# 转回字符后 return
pass这里的 pass 是待补全的占位语句。函数每次返回一个字符;主程序判断字符类别后传入对应的起点和长度。对其他字符则直接保留,不必送入转换函数。
输入与拼接关键点:保留消息中的空格。 消息行使用 input() 整行读取,不要 split(),也不要为了“清理输入”随意删掉首尾空格。循环中可以先用最直接的字符串累加方式理解:
python
result = ""
# 每得到一个 converted_char,就接到当前结果后面:
# result += converted_char参考解法用列表收集字符,最后 ''.join(...) 拼接,作用相同。循环中逐字符 print() 会多出换行,不符合整行输出要求。
样例密钥为 23:大写 I 的位置是 8,(8+23)%26=5,得到 F;数字 1 变成 (1+23)%10=4。所以样例开头的 I 变为 F,编号 19123 变为 42456,空格和句点保留。
易错点
- 合法模式扩大或漏写: 题面列出
e、E、encrypt、Encrypt和对应四种解密模式;ENCRYPT不在列表中,应为Wrong Mode,不能无条件转小写后接受。 - 三类字符混用一个环: 大写、小写分别保持大小写,数字按 10 循环,不能全部使用起点
'a'或长度 26。 - 编码与位置混淆: 取余前减去起点编码,取余后加回起点编码,再调用
chr()。 - 解密仍向加密方向移动: 解密应减去密钥;可用上表的
b → y检查。 - 空格、标点被删除或改变: 消息作为整行读取,其他字符原样接入结果。使用明确的英文字母和数字范围也可避免把中文、全角数字误当作待转换字符。
可测试加密模式、密钥 1、消息 Az9!,应得到 Ba0!;再用同一密钥解密 Ba0!,应回到 Az9!。两次检查能同时覆盖大小写、数字环绕和标点保留。
本题答案暂未公开
北京时间 2026/10/27 13:00:00 解锁
正在检查解锁状态…
正在载入加密答案…