Skip to content

2026-计算概论C-py作业3 ​

题集链接 ​

OpenJudge/计算概论C(py)/2026-计算概论C-py作业3

共 9 题。题面、知识点、解题提示、易错点与完整参考解析均已公开。

01:奇偶数判断 ​

题目描述 ​

给定一个整数,判断该数是奇数还是偶数。

输入

输入仅一行,一个大于零的正整数n。

输出

输出仅一行,如果n是奇数,输出odd;如果n是偶数,输出even。

样例输入

5

样例输出

odd

来源

北京大学 计算概论 06

解题提示

本题知识点: 第 2 章《基本数据类型》: 整数转换与取余 %;第 3 章《程序控制结构与异常处理》: if/else 双分支,根据条件选择一种输出。

  1. input() 得到的是字符串,要先转换成整数,才能判断除以 2 后的余数。
  2. 偶数能被 2 整除,余数为 0;奇数除以 2 的余数为 1。先写清楚“条件成立时属于哪一类”,再安排两个分支。
  3. 两个分支只执行其中一个,最后输出题目指定的 even 或 odd。

判断关键点: 可以先单独检查条件的真假:

python
remainder = n % 2
is_even = remainder == 0

这里 = 是保存结果,== 是比较是否相等。用 1、2、5 分别检查,结果应为 odd、even、odd;不要只用样例里的奇数检查程序。

易错点

  • 运算符用错: / 2 得到商,不能用来判断奇偶;应该观察 % 2 的余数。
  • 分支对应颠倒: 余数为 0 对应 even,不是 odd。如果直接把余数作为条件,1 为真、0 为假,要确认分支含义。
  • 语法与输出: if、else 后需要冒号,分支内需要缩进;只输出小写英文单词,不加中文解释或输入提示。

题解 ​

思路 ​

先求整数除以 2 的余数,再按是否为 0 分成两个分支;对照题目使用英文输出。

知识点 ​

分支结构第3章程序的控制结构

代码(尹思源) ​

python
num = int(input())
if num % 2:
    print("odd")
else:
    print("even")

02:简单计算器 ​

题目描述 ​

一个最简单的计算器,支持+, -, *, / 四种运算。仅需考虑输入输出为整数的情况(除法结果就是商,忽略余数)

输入

输入只有一行,共有三个参数,其中第1、2个参数为整数,第3个参数为操作符(+,-,*,/)。

输出

输出只有一行,一个整数,为运算结果。然而:

  1. 如果出现除数为0的情况,则输出:Divided by zero!
  2. 如果出现无效的操作符(即不为 +, -, *, / 之一),则输出:Invalid operator!

样例输入

1 2 +

样例输出

3

解题提示

本题知识点: 第 2 章《基本数据类型》: split()、整数转换、四则运算及整除;第 3 章《程序控制结构与异常处理》: if/elif/else 多分支与嵌套判断。

  1. 一行输入中有三个字段。先用 split() 拆开,将前两个字段分别转成整数,运算符保留为字符串,例如 "+"。
  2. 按运算符选择加、减、乘、除四种情况;其余字符统一进入无效运算符的分支。使用 elif 可以保证只选择一条运算路径。
  3. 在除法分支内部先判断第二个数是否为 0。为 0 时输出 Divided by zero!,否则计算整数商;无效运算符输出 Invalid operator!。

除法关键点: 本题要求忽略余数,商向零截断。Python 的 // 是向下取整,两者在负数时可能不同:-7 // 3 是 -3,本题应得到 -2。可以先对绝对值求整商,再根据两数是否异号确定符号:

python
magnitude = abs(a) // abs(b)  # 仅在 b 不为 0 时计算
opposite_signs = (a < 0) != (b < 0)

不要把 / 的浮点结果直接当整数输出。先检查 7 3 /、-7 3 /、7 -3 /,应分别得到 2、-2、-2;再检查 5 0 +,它仍应正常得到 5。

易错点

  • 统一转换三个字段: 运算符不能转换成整数;要先拆分,再按各字段的类型处理。
  • 零判断位置错误: 第二个数为 0 不代表所有运算都出错,只有除法需要拦截除数为零;也不能先做除法再检查。
  • 负数整商错误: 直接使用 a // b 可能把负商向下取整;int(a / b) 虽然向零截断,但会经过浮点数,大整数时可能损失精度。
  • 提示语不一致: 保留 Divided by zero!、Invalid operator! 的大小写、空格和感叹号,输出中不加自己的说明。

题解 ​

思路 ​

注意输出结尾的感叹号

一行读入两个整数和运算符,先按运算符选择分支。除法分支先检查除数,再计算整数商。

知识点 ​

分支结构第3章程序的控制结构

代码(尹思源) ​

python
num1, num2, op = input().split()
num1 = int(num1)
num2 = int(num2)
if op == "+":
    print(num1 + num2)
elif op == "-":
    print(num1 - num2)
elif op == "*":
    print(num1 * num2)
elif op == "/":
    if num2 == 0:
        print("Divided by zero!")
    else:
        quotient = abs(num1) // abs(num2)
        print(-quotient if (num1 < 0) != (num2 < 0) else quotient)
else:
    print("Invalid operator!")

代码(钱丽艳) ​

python
s = input().split()
x, y, op = s[0], s[1], s[2]
if int(y) == 0 and op == "/":
    print("Divided by zero!")
elif op not in ["+", "-", "*", "/"]:
    print("Invalid operator!")
else:
    if op == "+":
        print(int(x) + int(y))
    elif op == "-":
        print(int(x) - int(y))
    elif op == "*":
        print(int(x) * int(y))
    else:
        quotient = abs(int(x)) // abs(int(y))
        print(-quotient if (int(x) < 0) != (int(y) < 0) else quotient)

03:计算邮资 ​

题目描述 ​

根据邮件的重量和用户是否选择加急计算邮费。计算规则:重量在1000克以内(包括1000克), 基本费8元。超过1000克的部分,每500克加收超重费4元,不足500克部分按500克计算;如果用户选择加急,多收5元。

输入

输入一行,包含整数和一个字符,以一个空格分开,分别表示重量(单位为克)和是否加急。如果字符是y,说明选择加急;如果字符是n,说明不加急。

输出

输出一行,包含一个整数,表示邮费。

样例输入

1200 y

样例输出

17

来源

1858

解题提示

本题知识点: 第 2 章《基本数据类型》: 混合类型输入、数学函数;第 3 章《程序控制结构与异常处理》: 边界判断、独立条件与累加。

  1. 用 input().split() 读入重量和加急标记,把重量转成整数。
  2. 先判断重量边界: weight <= 1000 时,邮费为 8 元;weight > 1000 时,基本费仍是 8 元,另加超重费。
  3. 超重时,计算超出部分需要收几档,每档加 4 元。下面给出三种方法,任选一种即可。
  4. 再独立判断加急标记:是 "y" 就在已经算出的邮费上加 5 元。

直接对照重量区间:

重量范围超重费不加急的邮费
weight <= 10000 元8 元
1000 < weight <= 15004 元12 元
1500 < weight <= 20008 元16 元
2000 < weight <= 250012 元20 元

后续每增加一个 500 克区间,邮费再加 4 元。注意右边界属于当前区间:1000 克收 8 元,1001 克收 12 元;1500 克仍收 12 元,1501 克才收 16 元(均不加急)。不需要把所有区间逐个写成 elif,math.ceil() 会算出对应档数。

超重档数的三种算法(下面的代码都只在 weight > 1000 时使用;算出 blocks 后,超重费就是 blocks * 4。)

方法一:math.ceil() 向上取整
python
import math
extra = weight - 1000
blocks = math.ceil(extra / 500)

把超出重量除以 500,有不足一档的部分就向上取整:超出 200 克,0.4 向上取整为 1;超出 500 克,1.0 仍为 1;超出 501 克,1.002 向上取整为 2。

方法二:整数公式
python
extra = weight - 1000
blocks = (extra + 499) // 500

适用于本题的整数克数。先加 499,再整除 500,就能把不足 500 克的部分也计入一档:(1 + 499) // 500 = 1,(500 + 499) // 500 = 1,(501 + 499) // 500 = 2。

公式不容易记时,可以选择方法一或下面的条件判断方法。

方法三:用 if 判断是否恰好整除
python
extra = weight - 1000
if extra % 500 == 0:
    blocks = extra // 500
else:
    blocks = extra // 500 + 1

直接分两种情况:恰好是 500 克的整数倍,就按完整档数收费;不是整数倍,就多算一档。超出 500 克时余数为 0,收 1 档;超出 501 克时余数为 1,收 2 档。

样例 1200 y:超过 1000 克但不超过 1500 克,普通邮费 12 元;加急再加 5 元,最终为 17 元。

易错点

  • 超重范围算错: 只对超过 1000 克的部分分档,不是对邮件的全部重量分档;基本费仍需保留。
  • 不足一档被舍去: extra // 500 会漏收不足 500 克的部分;1000 克不超重,1001 克就需要一档超重费。
  • 把独立条件写成互斥分支: 超重后仍可能加急,不能用 elif 让二者只能收取一种费用。
  • 字符串与数值混淆: 加急标记与 "y" 比较;邮费输出一个整数,不加“元”或提示文字。

题解 ​

思路 ​

先记基本邮费,再分别考虑超重费和加急费。只对超过 1000 克的部分按 500 克向上取整。

知识点 ​

分支结构第3章程序的控制结构

代码(尹思源) ​

python
weight, quick = input().split()
weight = int(weight)
price = 8
if quick == "y":
    price += 5
if weight > 1000:
    price += (weight - 1000 + 499) // 500 * 4
print(price)

代码(钱丽艳) ​

python
import math

s = input().split()
weight, urgent = int(s[0]), s[1]
money = 8
if urgent.lower() == "y":
    money += 5
if weight > 1000:
    money += math.ceil((weight - 1000) / 500) * 4  # math.ceil()为向上取整函数
print(money)

04:奥运奖牌计数 ​

题目描述 ​

2008年北京奥运会,A国的运动员参与了n天的决赛项目(1≤n≤17)。现在要统计一下A国所获得的金、银、铜牌数目及总奖牌数。

输入

输入n+1行,第1行是A国参与决赛项目的天数n,其后n行,每一行是该国某一天获得的金、银、铜牌数目,以一个空格分开。

输出

输出1行,包括4个整数,为A国所获得的金、银、铜牌总数及总奖牌数,以一个空格分开。

样例输入

3
1 0 3
3 1 0
0 3 0

样例输出

4 4 3 11

解题提示

本题知识点: 第 2 章《基本数据类型》: 一行多个整数的转换与累加赋值;第 3 章《程序控制结构与异常处理》: for/range 控制确定次数的循环。

  1. 先读取天数 n,再把金、银、铜三个累计量初始化为 0。它们记录的是“到目前为止的总数”。
  2. 循环执行 n 次,每次只读取当天的一行数据,拆出三种奖牌数量,分别增加到对应的累计量中。
  3. 全部天数处理完后,再把三种累计量相加得到奖牌总数;按金、银、铜、总数的顺序一次输出四个整数。

累加关键点: 当天数量和累计数量应使用不同变量。以金牌为例:

python
gold_total += daily_gold

这等价于 gold_total = gold_total + daily_gold。累计量要在循环外初始化,输出也放在循环结束之后。样例三天的金牌累计过程是 0 → 1 → 4 → 4;银牌、铜牌分别累计,最后应得到 4 4 3 11。还可以检查只有一天、当天奖牌全为 0 的情况。

易错点

  • 累计变成覆盖: gold_total = daily_gold 只保存当天数量,最后会丢失前几天的数据。
  • 每轮重新初始化: 把累计量设为 0 的语句放进循环,会导致只能统计最后一天。
  • 读取次数与输出位置: 天数所在的第一行不算奖牌数据;之后恰好读取 n 行,不在循环里每天输出一次。
  • 顺序或分隔符错误: 输出金、银、铜及总数,四项之间用空格,不输出列表括号、逗号或说明文字。

题解 ​

思路 ​

先读天数,分别初始化金、银、铜三个累计量。循环读入每天的数据,对应相加,最后计算总奖牌数。

知识点 ​

循环结构第3章程序的控制结构

代码(尹思源) ​

python
n = int(input())
medals = [0, 0, 0]
for i in range(n):
    medal = list(map(int, input().split()))
    for j in range(3):
        medals[j] += medal[j]
print(medals[0], medals[1], medals[2], sum(medals))

代码(钱丽艳) ​

python
num = int(input())
sumGN = sumSN = sumCN = 0
for i in range(num):
    strN = input().split()
    sumGN += int(strN[0])
    sumSN += int(strN[1])
    sumCN += int(strN[2])
sumN = sumGN + sumSN + sumCN
print(f"{sumGN} {sumSN} {sumCN} {sumN}")

05:最长单词2 ​

题目描述 ​

一个以'.'结尾的简单英文句子,单词之间用空格分隔,没有缩写形式和其它特殊形式,求句子中的最长单词。

输入

一个以'.'结尾的简单英文句子(长度不超过500),单词之间用空格分隔,没有缩写形式和其它特殊形式。

输出

该句子中最长的单词。如果多于一个,则输出第一个

样例输入

I am a student of Peking University.

样例输出

University

解题提示

本题知识点: 第 2 章《基本数据类型》: 字符串切片、split() 和 len();第 3 章《程序控制结构与异常处理》: 遍历、条件更新与保留最优结果。

  1. 读取整句后,先去掉题目保证存在的句末句点,再用 split() 得到从左到右排列的单词。句点不属于最后一个单词。
  2. 用一个变量记录“目前找到的最长单词”。可以从第一个单词开始,之后依次检查其余单词。
  3. 比较当前单词与已记录单词的长度:只有当前单词严格更长时才替换;遍历结束后输出记录的单词。

更新关键点: 条件应该使用严格大于:

python
len(word) > len(longest)

如果长度相等,不更新,就能保留最先出现的单词。比如 cat dog. 应输出 cat,而不是 dog;I am a student. 应输出 student,不带句点。去掉末尾句点时,可以利用字符串切片保留它前面的所有字符。

易错点

  • 句点参与比较或输出: 最后一个单词多算一个字符,可能错误胜出;即使选对单词,也不能把句点一起输出。
  • 用 >= 更新: 同样长的后续单词会覆盖第一个,不符合题目的并列规则。
  • 比较字符串本身: word > longest 比较的是字典序,应比较 len(word) 与 len(longest)。
  • 输出位置错误: 记录最长单词的变量必须保留到循环结束,不能每轮都输出或重置。

题解 ​

思路 ​

先去掉句末的句点再分词。用一个变量记录目前最长单词,从左到右逐个比较长度。

知识点 ​

循环结构第3章程序的控制结构

代码(尹思源) ​

python
words = input()[:-1].split()
longest = None
for word in words:
    if longest is None or len(word) > len(longest):
        longest = word
print(longest)

代码(钱丽艳) ​

python
sentence = input().split()
lWord = ""
for i in sentence:                  # sentence为列表类型
    if i == sentence[-1]:           # 如果为最后一个单词,需要去掉结尾的“.”
        i = i[:-1]                 # 只去掉末尾句点,保留单词中的其他字符
    if len(i) > len(lWord):
        lWord = i
print(lWord)

06:计算直角三角形面积 ​

题目描述 ​

可以多次输入三角形三边,在满足下述条件的时候,计算三角形面积,不满足条件的时候,给出相应的提示信息。程序结束的条件是,将三边均输成0,程序结束时给出提示信息。

  1. 要求在一条input语句中输入三角形三边;

  2. 计算三角形面积的条件是:三边能构成三角形,并且构成的三角形是直角三角形

  3. 输入、输出范例:注意,输出的面积四舍五入保留小数点后一位,输入的三角形三边全为整数

    输入输出
    1 2 5not triangle, please input again
    1 1 1not right triangle, please input again
    3 4 56.0, please input again
    0 0 0program finished

输入

一行或多行,每行3个数字以空格分隔

输出

对应的语句

样例输入

1 2 5
1 1 1
3 4 5
0 0 0

样例输出

not triangle, please input again
not right triangle, please input again
6.0, please input again
program finished

解题提示

本题知识点: 第 2 章《基本数据类型》: 一行三个整数、平方和面积计算、固定精度输出;第 3 章《程序控制结构与异常处理》: while、break 与按优先顺序安排分支。排序可用于把三边按长短排列。

  1. 每轮用一次 input() 读取一组边长。先判断三边是否全部为 0;若是,输出 program finished 并结束循环,不再作三角形判断。
  2. 对其余输入,先确定最长边。设排序后的三边为 a ≤ b ≤ c,正长度且 a + b > c 才能组成三角形;不满足时输出对应提示,进入下一轮。
  3. 能组成三角形后,再检查勾股关系。若满足,a、b 就是两条直角边,用它们求面积,并按一位小数与固定后缀输出;否则输出非直角三角形的提示。

判断顺序关键点:

读取三边 → 全零结束 → 能否构成三角形 → 是否直角 → 面积

排序后可观察的勾股条件为:

python
a ** 2 + b ** 2 == c ** 2

面积是两条直角边乘积的一半。所有边长都是整数,平方比较可以直接使用整数运算。用 5 3 4 检查输入顺序变化,仍应输出 6.0, please input again;用 1 2 3 检查三角形不等式的等号边界。

易错点

  • 终止判断过晚或条件错误: 0 0 0 要输出结束提示,不是 not triangle;只要有一条边为 0 也不能直接当作结束。
  • 默认第三条边最长: 5 3 4 的斜边是第一个输入值;必须先确认三边的长短关系。
  • 三角形判定不严格: 两边之和等于第三边时不能构成三角形;边长还必须为正。
  • 只处理一组输入: 普通结果输出后应继续读取,只有全零才能终止。
  • 提示与格式遗漏: 两种错误提示、面积后的 , please input again、结束提示都要与题面一致;面积要显示一位小数,如 6.0。

题解 ​

思路 ​

每轮读入三条边,先检查是否全为 0。排序后先判断能否组成三角形,再检查勾股关系,满足时由两条直角边求面积。

知识点 ​

循环结构 分支结构第3章程序的控制结构

代码(尹思源) ​

python
while True:
    tri = map(int, input().split())
    a, b, c = sorted(tri)
    if a == 0 and b == 0 and c == 0:
        print("program finished")
        break
    elif a + b <= c:
        print(f"not triangle, please input again")
    elif a**2 + b**2 == c**2:
        print(f"{a*b/2:.1f}, please input again")
    else:
        print(f"not right triangle, please input again")

07:正常血压 ​

题目描述 ​

监护室每小时测量一次病人的血压,若收缩压在90 - 140之间并且舒张压在60 - 90之间(包含端点值)则称之为正常,现给出某病人若干次测量的血压值,计算病人保持正常血压的最长小时数。

输入

第一行为一个正整数n,n < 100 其后有n行,每行2个正整数,分别为一次测量的收缩压和舒张压,中间以一个空格分隔。

输出

输出仅一行,血压连续正常的最长小时数。

样例输入

4
100 80
90 50
120 60
140 90

样例输出

2

来源

习题(5-6) 医学部 2010 期末试题 周恺

解题提示

本题知识点: 第 3 章《程序控制结构与异常处理》: 范围判断、逻辑 and、循环、条件更新与连续区间统计。

  1. 读取测量次数 n,初始化两个计数:current 表示截至当前测量连续正常了多少小时,best 表示目前见过的最长连续正常时长。
  2. 每轮读取收缩压和舒张压。收缩压落在 [90, 140],并且舒张压落在 [60, 90],这一次才算正常;正常时把 current 加 1,异常时把它清零。
  3. 每次处理后,用新的 current 更新历史最大值。全部测量处理完后只输出 best。

状态关键点: 正常条件需要同时满足两项:

python
90 <= systolic <= 140 and 60 <= diastolic <= 90

两种计数职责不同:current 可以清零,best 只记录更大的结果。把一串测量抽象为“正常、正常、异常、正常、正常、正常”,current 依次是 1、2、0、1、2、3,最长时长是 3,不是正常总次数 5。

检查全部正常、全部异常和最长区间出现在最后这三种情况;90 60、140 90 都应被计为正常。

易错点

  • and 写成 or: 只有一项在范围内仍可能被算正常,题目要求两项同时满足。
  • 排除端点: 判断必须包含 90、140、60、90,不能用严格小于代替全部的 <=。
  • 把连续次数当总次数: 出现异常时必须清零当前连续次数,但不能把历史最长值一起清零。
  • 遗漏最后一段: 如果只在异常出现时结算最大值,最后连续正常的一段可能没有被记录;每轮更新最大值可避免遗漏。

题解 ​

思路 ​

同时维护当前连续正常次数和历史最长次数。两项血压都正常时增加当前次数,任一异常时把当前次数清零。

知识点 ​

循环结构第3章程序的控制结构

代码(尹思源) ​

python
n = int(input())
current = 0
longest = 0
for _ in range(n):
    a, b = map(int, input().split())
    if 90 <= a <= 140 and 60 <= b <= 90:
        current += 1
        longest = max(longest, current)
    else:
        current = 0
print(longest)

08:找出全部子串位置 ​

题目描述 ​

输入两个串s1,s2,找出s2在s1中所有出现的位置

两个子串的出现不能重叠。例如'aa'在 aaaa 里出现的位置只有0,2

输入

第一行是整数n 接下来有n行,每行两个不带空格的字符串s1,s2

输出

对每行,从小到大输出s2在s1中所有的出现位置。位置从0开始算 如果s2没出现过,输出 "no" 行末多输出空格没关系

样例输入

4
ababcdefgabdefab ab
aaaaaaaaa a
aaaaaaaaa aaa
112123323 a

样例输出

0 2 9 14
0 1 2 3 4 5 6 7 8
0 3 6
no

来源

Guo Wei

解题提示

本题知识点: 第 2 章《基本数据类型》: 字符串 find()、子串长度与从 0 开始的下标;第 3 章《程序控制结构与异常处理》: 多组数据循环、查找循环与终止条件。

  1. 先读取组数 n,每组拆出原串 s1 和目标串 s2,将本组查找起点设为 0,并准备记录找到的位置。
  2. 从当前起点向后查找:s1.find(s2, start) 返回匹配在整个原串中的下标;若返回 -1,本组查找结束。
  3. 找到时记录位置,并把下一次起点移动到此次匹配的末尾。完成本组后,在一行中依次输出全部位置;一个都没找到时输出小写 no。

非重叠关键点: 找到位置 position 后,下一次起点应为:

python
start = position + len(s2)

例如在 aaaa 中查找 aa:先得到 0,随后从 2 开始查找,得到 2,再从 4 开始查找并结束。结果是 0 2;从 1 开始会错误地得到重叠位置。

可以再检查 abcabc abc 得到 0 3、abc z 得到 no、ab ab 得到 0。每组数据的起点和结果都要重新初始化。

易错点

  • 用真假判断位置: 位置 0 是有效结果,但在布尔判断中为假;找不到的 -1 反而为真。应明确比较是否等于 -1。
  • 未移动起点: 一直从同一位置查找,会重复命中并形成死循环。
  • 只向后移一位: 对长度大于 1 的目标串会产生重叠匹配,必须跳过整个已匹配子串。
  • 切片后下标错位: 对截短后的字符串调用 find() 得到的是局部下标,需换算回原串位置;直接在原串中传入 start 更容易处理。
  • 多组数据串在一起: 每组单独输出一行;没有匹配时输出 no,不是 -1、空行或 No。

题解 ​

思路 ​

为每组数据设置一个起始位置,用 find 从该处查找。找到后记录下标,并把下一次起点移动到这次匹配的末尾。

知识点 ​

循环结构第3章程序的控制结构

代码(尹思源) ​

python
n = int(input())
for _ in range(n):
    s1, s2 = input().split()
    positions = []
    i = 0
    while i <= len(s1) - len(s2):
        if s1[i : i + len(s2)] == s2:
            positions.append(i)
            i += len(s2)  # 不允许重叠
        else:
            i += 1
    if positions:
        print(*positions)  # print(*positions) 会自动以空格分隔输出。
    else:
        print("no")

代码(钱丽艳) ​

python
n = int(input())
for i in range(1, n + 1):
    s1, s2 = input().split()
    start, end = 0, len(s1)
    if s2 in s1:
        while s1.find(s2, start, end) != -1:
            idn = s1.find(s2, start, end)  # sub如果包含在 str[strat:end] 中返回sub开始的索引值,否则返回-1
            print(idn, end=" ")
            start = idn + len(s2)
        print()
    else:
        print("no")

09:打印数字三角形 ​

题目描述 ​

输入行数n(1  <= n <=5),打印出由n行数字组成的正实心三角形,每行的数字范围为[1,2*n-1],每行的数字之间没有空格。

输入

输入只有一行,仅一个参数,即需要打印的行数n

输出

由n行数字组成的正实心三角形

样例输入

4

样例输出

   1
  123
 12345
1234567

解题提示

本题知识点: 第 2 章《基本数据类型》: 字符串重复、数字转字符串与输出拼接;第 3 章《程序控制结构与异常处理》: for/range、行列关系和嵌套循环。

  1. 用从 1 开始的行号 i 观察样例:第 1 行有 1 个数字,第 2 行有 3 个数字,第 3 行有 5 个数字,所以第 i 行数字个数为 2 * i - 1。
  2. 为让每行居中,先输出 n - i 个前导空格,再依次输出从 1 到 2 * i - 1 的数字。每一行的数字都从 1 重新开始。
  3. 可以先拼好一行再调用一次 print();也可以逐个打印,但要用 end="" 让空格和数字留在同一行,最后再换行。

行列关键点: 每一行由两部分组成:

python
left_padding = " " * (n - i)
digit_count = 2 * i - 1

若用 range 生成数字,要注意右端不包含:需要的最后一个数字是 2 * i - 1,结束参数要比它大 1。n=3 时三行分别有 2、1、0 个前导空格,数字部分是 1、123、12345。题目限制 n ≤ 5,因此最大的数字为 9,每个数字都占一个字符。

易错点

  • 打印成倒三角或直角三角形: 前导空格每行减少一个,数字个数每行增加两个;不要把这两种变化弄反。
  • range 少一个数字: 右端不包含,要检查每行最后一个数字是否确实输出。
  • 数字之间出现空格或换行: 逐个输出时默认 print() 会换行,打印多个参数时默认会插入空格;本题数字之间都不应有空格。
  • 删掉前导空格: 不对拼好的行使用 strip(),否则居中的缩进会丢失。
  • 每行数字未重置: 每行都从 1 开始,不是沿用上一行继续递增;用 n=1 和 n=5 检查最小、最大行数。

题解 ​

思路 ​

从第 1 行到第 n 行,分别确定前导空格数和数字个数。观察样例:数字个数依次是 1、3、5,左边空格每行少一个。

知识点 ​

循环结构第3章程序的控制结构

代码(尹思源) ​

python
n = int(input())
for i in range(1, n + 1):
    space = (n - i) * " "
    num = [str(j) for j in range(1, i * 2)]
    print(space + "".join(num))

代码(钱丽艳) ​

python
n = int(input())
for i in range(1, n+1):
    for j in range(1, n-i+1):  # 打空格。 空格的个数:(一行总字符数-一行数字字符数)/2=((2*n-1)-(2*i-1))/2=n-i
        print(" ", end="")
    for j in range(1, 2*i):    # 打数字
        print(j, end="")
    print("")

课程资料由授课教师、助教与同学共同积累。