PyPython习题册

题目解析

69个编程单元,按专题归类。每题包含题目要求、相关知识、参考答案与方法归纳。

1 基础输入与Turtle绘图

专题方法

绘图与参数化

要点方法
基本结构设状态→移动/绘图→更新方向→重复
几何参数正n边形外角360/n;画线与抬笔移动分开
函数复用相同图形封装;位置/大小/颜色作为参数

P01 字符串原样输出

输入代码并练习

1. 题目要求

读入一整行字符串,原样输出(含中间空格)。

查看原题说明

从键盘输入一个字符串,并在屏幕上输出它。

输入示例
hello world
输出示例
hello world

2. 相关知识

本题用到的写法含义 / 用法
input()读一行→str;不自动按空格分开
print(s)输出s并换行
3. 参考答案
s = input()
print(s)

方法归纳:整行文本题先保留原串;题目要求分词时再split。

P02 绘制正方形

输入代码并练习

1. 题目要求

用Turtle画边长100的正方形。

查看原题说明

利用turtle绘制边长为100的正方形,并在答题框内依次黏贴代码和运行效果截图。windows系统中可以同时按下 shift + win + s 三个键来实现屏幕截图。

2. 相关知识

本题用到的写法含义 / 用法
range(4)循环4次,循环变量依次为0、1、2、3
t.fd(100)沿当前朝向前进100像素,落笔时画线
t.right(90)从当前朝向向右旋转90度,位置不变
3. 参考答案
import turtle as t
for i in range(4):
    t.fd(100)
    t.right(90)
t.done()

方法归纳:正n边形重复n次,每次前进一条边并转外角360/n。

易错点:绝对角度变式:每轮先t.seth(-90*i)再前进。

P03 绘制正N边形

输入代码并练习

1. 题目要求

输入逗号分隔的边数n、边长L,画正n边形;n≥3。

查看原题说明

利用turtle绘制正N边形。其中边数、边长均由用户键盘输入指定。注意:测试代码时,输入的边数应能被360整除。windows系统中可以同时按下 shift + win + s三个键来实现屏幕截图。

2. 相关知识

本题用到的写法含义 / 用法
n,L = eval(input())课堂逗号输入,如6,100
360 / n多边形外角;不是内角
3. 参考答案
import turtle as t
n, sidelen = eval(input())
for i in range(n):
    t.fd(sidelen)
    t.right(360 / n)
t.done()

方法归纳:边数与边长参数化,改n即可画同一类图形。

易错点:课堂要求n整除360时可用//;一般n用/。range参数补为n。

P04 绘制单个苯环

输入代码并练习

1. 题目要求

画外边长100、内侧线段长80的苯环示意。

查看原题说明

利用turtle库在IDLE下使用文件式编程方法,按照课件上提供的算法编写绘制一个苯环的程序(外环边长100,内环边长80)。请将代码和运行效果截图依次黏贴在答题框内。windows系统中可以同时按下shift + win + s 三个键来实现屏幕截图。

2. 相关知识

本题用到的写法含义 / 用法
t.left(60)向左转60度,即正六边形的外角
t.pu() / t.pd()分别抬笔、落笔;决定后续移动是否画线
t.seth(angle)直接设定绝对朝向,不是相对旋转
i % 2 == 0偶数段落笔,奇数段抬笔
3. 参考答案
import turtle as t
t.pensize(3)
for i in range(6):
    t.fd(100)
    t.left(60)
t.pu()
t.seth(60)
t.fd(20)
t.seth(0)
for i in range(6):
    if i % 2 == 0:
        t.pd()
    else:
        t.pu()
    t.fd(80)
    t.left(60)
t.done()

方法归纳:外环连续绘制,内侧按段号奇偶控制画笔状态。

易错点:转移内环前须抬笔;否则产生多余连线。

P05 绘制30个随机正多边形

输入代码并练习

1. 题目要求

画30个随机位置、颜色、大小、边数的正多边形。

查看原题说明

编写程序,利用turtle绘制30个不同颜色,不同位置,不同大小的正N边形。请在答题框内先黏贴你的代码,然后黏贴运行窗口截图。windows系统中可以同时按下 shift + win + s 三个键来实现屏幕截图。

2. 相关知识

本题用到的写法含义 / 用法
randint(a,b)取含两端的随机整数
colormode(255)RGB三分量均0—255
双层循环外层30个图;内层n条边
3. 参考答案
import turtle as t
import random
t.setup(800, 600)
t.bgcolor('black')
t.colormode(255)
t.speed(0)
t.pensize(3)
t.hideturtle()
for i in range(30):
    t.pu()
    t.goto(random.randint(-300, 250), random.randint(-220, 220))
    t.pencolor(*(random.randint(0, 255) for _ in range(3)))
    n = random.randint(3, 10)
    length = random.randint(20, 70)
    t.pd()
    for j in range(n):
        t.fd(length)
        t.left(360 / n)
t.done()

方法归纳:先随机生成参数,再调用同一绘图步骤。

易错点:随机抽样可能重复;移动下一个图形前抬笔。

P06 无角正方形

输入代码并练习

1. 题目要求

画四边仅中段有线、四角留空的“无角正方形”。

查看原题说明

用抬笔与落笔交替画四边,每边两端各留50像素空隙,中段画100像素。

2. 相关知识

本题用到的写法含义 / 用法
pu → fd(50)先走空白50
pd → fd(100)只画中段100
pu → fd(50) → left(90)再留空50并转角
3. 参考答案
import turtle as t
t.setup(800, 600, 200, 200)
t.pensize(5)
t.penup()
for i in range(4):
    t.fd(50)
    t.pendown()
    t.fd(100)
    t.penup()
    t.fd(50)
    t.left(90)
t.done()

方法归纳:把一条边拆成“空白—线段—空白”,外层重复四次。

P07 交错三环

输入代码并练习

1. 题目要求

用红、绿、蓝画三个交错圆,半径80,笔宽5。

查看原题说明

画笔宽5,依次以红、绿、蓝绘制半径80的三个圆,每次左转120度。

2. 相关知识

本题用到的写法含义 / 用法
t.circle(80)画半径80的圆,正半径的圆心在当前左侧
t.left(120)向左旋转120度,使下一个圆的圆心方向改变
3. 参考答案
import turtle as t
t.pensize(5)
for color in ('red', 'green', 'blue'):
    t.pencolor(color)
    t.circle(80)
    t.left(120)
t.done()

方法归纳:重复相同图形并固定旋转角度,形成旋转对称图案。

P08 五角星与九角星

输入代码并练习

1. 题目要求

红色五角星;变式为蓝色九角星。

查看原题说明

画红色填充五角星;将其修改为蓝色九角星。

2. 相关知识

本题用到的写法含义 / 用法
五角星5次前进,每次right(144)
九角星9次前进,每次right(80)
begin_fill/end_fill围住整段星形绘制过程
3. 参考答案
import turtle as t
t.fillcolor('red')
t.begin_fill()
for i in range(5):
    t.fd(200)
    t.right(144)
t.end_fill()
t.done()

方法归纳:星形不是普通多边形;转角要体现跨顶点连线。

易错点:九角星只改颜色、循环次数与转角,不能只改次数。

P09 太阳花

输入代码并练习

1. 题目要求

红笔黄填充,重复前进200、左转170°,形成太阳花。

查看原题说明

画笔红色、填充黄色,重复前进200并左转170度,回到起点附近时停止。

2. 相关知识

本题用到的写法含义 / 用法
pos() / abs(pos())当前位置向量 / 到原点距离
while True + break重复到满足闭合条件
abs(t.pos()) < 1以容差判断回到原点
3. 参考答案
import turtle as t
t.color('red', 'yellow')
t.begin_fill()
while True:
    t.fd(200)
    t.left(170)
    if abs(t.pos()) < 1:
        break
t.end_fill()
t.done()

方法归纳:固定边长与转角反复绘制,闭合后结束填充。

易错点:坐标含浮点误差,不直接要求位置精确等于(0,0)。

P10 随机多个苯环与七色苯环

输入代码并练习

1. 题目要求

封装苯环函数;随机位置和边长,依次画红橙黄绿青蓝紫七色苯环。

查看原题说明

将单苯环封装为函数,可指定位置、朝向、颜色、边长;随机选取位置和边长,依次绘制红橙黄绿青蓝紫七色苯环。

2. 相关知识

本题用到的写法含义 / 用法
def drawbenring(pos,angle,clr,L)把绘图差异写成参数
goto + seth + pencolor每次调用先重设位置、方向、颜色
for clr in colors颜色按给定次序,不随机选颜色
3. 参考答案
import turtle as t
import random

def drawbenring(pos, angle, clr, sidelen):
    t.pu()
    t.goto(pos)
    t.pencolor(clr)
    t.seth(angle)
    t.pd()
    for i in range(6):
        t.fd(sidelen)
        t.left(60)
    t.pu()
    t.seth(angle + 60)
    t.fd(20)
    t.seth(angle)
    for i in range(6):
        if i % 2 == 0:
            t.pd()
        else:
            t.pu()
        t.fd(sidelen - 20)
        t.left(60)

t.speed(0)
for clr in ('red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple'):
    pos = (random.randint(-250, 250), random.randint(-200, 200))
    drawbenring(pos, 0, clr, random.randint(40, 100))
t.done()

方法归纳:“一个图形的函数”+“多次生成参数调用”可复用到随机多边形。

易错点:函数沿用内边长L−20,故L必须大于20;七色调用由整理者补全。

2 数字计算与统计

专题方法

公式计算与输出

要点方法
读数据整数int,实数float,多值map+split
计算单位统一后写公式;幂运算**
输出固定小数f格式;至少几份用ceil

P11 等差数列第n项

输入代码并练习

1. 题目要求

一行输入a1、a2、n;输出等差数列第n项。

查看原题说明

题目描述给出一个等差数列的前两项a1和a2,求数列中第n项是多少?输入格式一行,包含三个用空格隔开的整数,分别表示a1、a2和n。输出格式一个整数,即数列中第n项的值。

输入示例
1 4 100
输出示例
298

2. 相关知识

本题用到的写法含义 / 用法
map(int,input().split())空格拆分→逐项转整数
a1+(n-1)*(a2-a1)首项+(项数−1)×公差
3. 参考答案
a1, a2, n = map(int, input().split())
ans = a1 + (n - 1) * (a2 - a1)
print(ans)

方法归纳:先写数学公式,再逐项映射为变量;负公差同样适用。

P12 人口增长

输入代码并练习

1. 题目要求

输入人口基数x(亿)和年数n;年增0.1%,输出n年后人口,固定4位小数。

查看原题说明

题目描述我国现有x亿人口,如果按照每年0.1%的增长速度,n年后将有多少人?输入格式一行,包含两个整数x和n,分别是人口基数和年数,以空格分隔。输出格式输出最后的人口数,以亿为单位,保留到小数点后4位。

输入示例
13 10
输出示例
13.1306

2. 相关知识

本题用到的写法含义 / 用法
x * 1.001 ** n按复利增长;0.1%=0.001
f"{ans:.4f}"f启用插值;花括号放ans;.4f固定4位、补尾零
3. 参考答案
x, n = map(int, input().split())
ans = x * (1 + 0.001) ** n
print(f'{ans:.4f}')

方法归纳:初值×(1±变化率)**次数:人口、利息、衰减同一模板。

易错点:输出要求固定小数位,不能只用round。

P13 球的体积

输入代码并练习

1. 题目要求

输入球半径r;π取3.14,输出体积,固定2位小数。

查看原题说明

题目描述输入球的半径,计算并输出球的体积(保留到小数点后2位)。这里取圆周率为3.14。

输入示例
4
输出示例
267.95

2. 相关知识

本题用到的写法含义 / 用法
float(input())半径可能有小数
4/3 * 3.14 * r**3**是幂,不是^
f"{ans:.2f}"两位小数且补尾零
3. 参考答案
r = float(input())
ans = 4 / 3 * 3.14 * r ** 3
print(f'{ans:.2f}')

方法归纳:几何计算:读实数→公式→按指定精度输出。

易错点:题目给定π时不用math.pi替代。

P14 三次多项式求值

输入代码并练习

1. 题目要求

一行实数x,a,b,c,d;求ax³+bx²+cx+d,固定7位小数。

查看原题说明

题目描述对于多项式 f(x)=a*x**3+b*x**2+c*x+d,现从键盘输入x,a,b,c,d的值,计算f(x)的值。输入格式仅一行,包含五个实数,分布代表x,a,b,c,d的值。输出格式一个实数,即f(x)的值,保留到小数点后7位。

输入示例
2.31 1.2 2 2 3
输出示例
33.0838692

2. 相关知识

本题用到的写法含义 / 用法
map(float,...)多个实数同时读取
x**3 / x**2三次项 / 二次项
f"{res:.7f}"固定7位小数
3. 参考答案
x, a, b, c, d = map(float, input().split())
res = a * x ** 3 + b * x ** 2 + c * x + d
print(f'{res:.7f}')

方法归纳:公式逐项实现;也可改写为((a*x+b)*x+c)*x+d。

易错点:输入顺序以x开头,不能按字母顺序读取。

P15 大象喝水

输入代码并练习

1. 题目要求

输入桶高h、半径r(cm);喝够20L需几桶?π取3.14159。

查看原题说明

题目描述一只大象口渴了,要喝20升水才能解渴。但现在只有一个深h厘米,底面半径位r厘米的小圆桶(h和r都是整数)。问大象至少要喝多少桶水才会解渴。输入格式一行,包含用空格隔开的两个整数,分别代表h和r。输出格式一个整数,表示大象至少要喝水的桶数。注意本题计算时圆周率值取3.14159。

输入示例
23 11
输出示例
3

2. 相关知识

本题用到的写法含义 / 用法
v=pi*r**2*h每桶体积:cm³
20*1000/v先统一20L=20000cm³
math.ceil(x)向上取整,2.1桶需3桶
3. 参考答案
import math 
h, r = map(int, input().split())
v = h * 3.14159 * r ** 2
print(math.ceil(20 * 1000 / v))

方法归纳:“至少几份才能够”→总需求/每份量,再向上取整。

易错点:必须先统一单位;有效输入要求h、r>0。

P16 五个数的基本统计量

输入代码并练习

1. 题目要求

输入5个逗号分隔的数;输出最大、最小、均值、样本标准差。

查看原题说明

输入五个逗号分隔的数,输出最大值、最小值、均值和样本标准差。

输入示例
1,3,5,7,9
输出示例
最大值为: 9
最小值为: 1
平均值为: 5.0
标准差为: 3.1622776601683795

2. 相关知识

本题用到的写法含义 / 用法
max/min直接接多个数
mean=sum/5均值
dev=(平方离差和/4)**0.55个样本,分母5−1
3. 参考答案
a, b, c, d, e = eval(input())
mean = (a + b + c + d + e) / 5
dev = (((a - mean) ** 2 + (b - mean) ** 2
        + (c - mean) ** 2 + (d - mean) ** 2
        + (e - mean) ** 2) / 4) ** 0.5
print('最大值为:', max(a, b, c, d, e))
print('最小值为:', min(a, b, c, d, e))
print('平均值为:', mean)
print('标准差为:', dev)

方法归纳:均值先算出,再计算各数与均值的平方差。

易错点:样本标准差分母n−1;总体标准差才除n。

P17 任意多个数的基本统计量

输入代码并练习

1. 题目要求

输入逗号分隔的至少2个数;计算极值、均值和样本标准差。

查看原题说明

输入逗号分隔的至少两个数,计算最大值、最小值、均值与样本标准差。

2. 相关知识

本题用到的写法含义 / 用法
len(values) / sum(values)样本数 / 总和
sum((x-mean)**2 for x in values)逐项计算→求和
/(n-1) + **0.5样本标准差
3. 参考答案
values = eval(input())
mean = sum(values) / len(values)
dev = (sum((x - mean) ** 2 for x in values) / (len(values) - 1)) ** 0.5
print('最大值为:', max(values))
print('最小值为:', min(values))
print('平均值为:', mean)
print('标准差为:', dev)

方法归纳:固定5个数→容器存任意多个数,公式中的5改为n。

易错点:n至少2;单个数既不形成所需元组,也无法算样本标准差。

3 字符串基础与图案

专题方法

图案与位置

要点方法
对齐比较按同一索引比较→计数→比值
回文s==s[::-1];数字先str
文本图案按行号写空格数、字符数,不凭图估空格

P18 DNA序列相关性

输入代码并练习

1. 题目要求

读阈值t与两条等长非空DNA(长度≤500);相同位置碱基比例≥t输出yes,否则no。

查看原题说明

题目描述为了获知基因序列在功能和结构上的相似性,经常需要将几条不同序列的 DNA进行比对,以判断该比对的DNA 是否具有相关性。现比对两条长度相同的 DNA 序列。首先定义两条 DNA 序列相同位置的碱基为一个碱基对,如果一个碱基对中的两个碱基相同的话,则称为相同碱基对。计算相同碱基对占总碱基对数量的比例,如果该比例大于等于给定阈值时则判定该两条DNA 序列是相关的,否则不相关。输入格式有三行。第一行为一个[0, 1] 范围内实数,表示用来判定出两条 DNA 序列是否相关的阈值,随后 2 行是两条 DNA 序列(长不大于 500)。输出格式若两条 DNA 序列相关,则输出 "yes" ,否则输出"no"。

输入示例
0.85
ATCGCCGTAAGTAACGGTTTTAAATAGGCC
ATCGCCGGAAGTAACGGTCTTAAATAGGCC
输出示例
yes

2. 相关知识

本题用到的写法含义 / 用法
range(len(s1)) + s1[i]==s2[i]同一位置逐项比较
cnt += 1计相等位置个数,不是计某字符总数
cnt/len(s1) >= t比例含阈值等号
3. 参考答案
t = float(input())
s1 = input()
s2 = input()
cnt = 0
for i in range(len(s1)):
    if s1[i] == s2[i]:
        cnt += 1
if cnt / len(s1) >= t:
    print('yes')
else:
    print('no')

方法归纳:对齐比较→计数→除以总长:适用于序列相似率、答题正确率。

P19 回文判断

输入代码并练习

1. 题目要求

输入无空白字符串(长度≤100);回文输出yes,否则no。

查看原题说明

题目描述输入一个字符串,判断该字符串是否回文。回文是指顺读和倒读都一样的字符串。输入格式输入为一行字符串(字符串中没有空白字符,字符串长度不超过100 )。输出格式如果字符串是回文,输出"yes",否则输出"no"。

输入示例
abcdedcba
输出示例
yes

2. 相关知识

本题用到的写法含义 / 用法
s[::-1]步长−1,整串逆序
s == s[::-1]正读=倒读即回文
数字变式先s=str(n)再比较
3. 参考答案
s = input()
if s == s[::-1]:
   print('yes')
else:
   print('no')

方法归纳:字符串回文、数字回文共用一个模板;只在输入转换上不同。

易错点:不要写成s[-1],那只取最后一个字符。

P20 字符三角形

输入代码并练习

1. 题目要求

一行输入字符c、正整数n;输出n行居中实心三角形。

查看原题说明

题目描述根据给定的字符和行数,输出三角形图案。输入格式一行,为一个字符c和一个正整数n,用空格隔开输出格式输出一个以字符c填充的三角形,该三角形的行数为n

输入示例
* 4
输出示例
   *
  ***
 *****
*******

2. 相关知识

本题用到的写法含义 / 用法
range(1,n+1)行号从1到n
" "*(n-i)左侧空格数
c*(2*i-1)每行字符数1、3、5……
3. 参考答案
c, n = input().split()
n = int(n)
for i in range(1, n + 1):
   print(' ' * (n - i) + c * (2 * i - 1))

方法归纳:先用行号i表达“空格数+字符数”,再循环输出。

易错点:i从0开始时公式应同步改写;空格不能凭图猜。

P21 五行菱形

输入代码并练习

1. 题目要求

输入字符c;输出字符数1、3、5、3、1的五行菱形。

查看原题说明

题目描述给你一个字符,希望你能用它构造一个对角线长5个字符,倾斜放置的菱形。输入格式输入只有一行,包含一个字符输出格式该字符构成的菱形

输入示例
*
输出示例
  *
 ***
*****
 ***
  *

2. 相关知识

本题用到的写法含义 / 用法
字符串重复3*c、5*c
前导空格依次2、1、0、1、2
3. 参考答案
c = input()
print('  ' + c)
print(' ' + 3 * c)
print(5 * c)
print(' ' + 3 * c)
print('  ' + c)

方法归纳:菱形=向上增长三角形+向下递减三角形。

易错点:中间行只输出一次;图案的空格也属于答案。

P22 正方形或菱形

输入代码并练习

1. 题目要求

读Z或L,再读边长n;Z输出n×n实心方形,L输出2n−1行菱形。

查看原题说明

题目描述根据输入的信息,打印正方形或菱形图案。输入格式两行。第一行为一个大写字母,Z表示输出正方形,L表示输出菱形。第二行为一个正整数n,表示输出图形的边长。输出格式参考样例,输出相应的图形。

输入示例
Z
3
输出示例
***
***
***

2. 相关知识

本题用到的写法含义 / 用法
"*"*n方形每行n个星号
菱形上半部i=1…n:空格n−i,星号2i−1
菱形下半部i=1…n−1:空格i,星号2n−1−2i
3. 参考答案
shape = input()
n = int(input())
if shape == 'Z':
   for i in range(n):
       print('*' * n)
else:
   for i in range(1, n + 1):
       print(' ' * (n - i) + '*' * (2 * i - 1))
   for i in range(1, n):
       print(' ' * i + '*' * (2 * n - 1 - 2 * i))

方法归纳:“选择图形”由分支控制;“输出每行”由循环控制。

易错点:下半部从收缩一行开始,避免重复最宽行。

P23 空心或实心矩形

输入代码并练习

1. 题目要求

一行h,w,c,flag:3≤h≤10,5≤w≤10;flag=0空心,1实心。

查看原题说明

输入h、w、字符c、标志flag,以空格隔开。3<=h<=10,5<=w<=10;flag=0为空心,flag=1为实心。输出对应矩形。

输入示例
3 5 @ 0
输出示例
@@@@@
@   @
@@@@@

2. 相关知识

本题用到的写法含义 / 用法
边界行c*w
空心中间行c+" "*(w-2)+c
实心中间行仍为c*w
3. 参考答案
h, w, c, flag = input().split()
h, w, flag = map(int, (h, w, flag))
print(w * c)
for i in range(h - 2):
    if flag == 0:
        print(c + (w - 2) * ' ' + c)
    else:
        print(w * c)
print(w * c)

方法归纳:先区分边界与内部,再决定内部输出空格还是填充字符。

4 字符串处理与格式化

专题方法

字符串变换步骤

要点方法
编码ord字符转数,chr数转字符;循环位移取模26
规范化大小写、空格、前后缀各自处理
重组输出split拆分→处理每项→join或格式化重接

P24 数字字符计数

输入代码并练习

1. 题目要求

读一行长度≤255的字符串;统计其中0—9字符个数。

查看原题说明

题目描述输入一行字符,统计出其中数字字符的个数。输入格式 一行字符串,总长度不超过255。输出格式一个整数,表示统计结果。

输入示例
Peking University is set up at 1898.
输出示例
4

2. 相关知识

本题用到的写法含义 / 用法
for c in s按字符遍历,空格也保留
"0" <= c <= "9"匹配ASCII十进制数字
ans += 1每命中一个字符加1
3. 参考答案
s = input()
ans = 0
for c in s:
   if '0' <= c <= '9':
       ans += 1
print(ans)

方法归纳:遍历+分类条件+计数器:可改成字母、空格、标点计数。

易错点:不要把整个字符串转int;isdigit的范围也不只ASCII。

P25 小写凯撒加密

输入代码并练习

1. 题目要求

读偏移整数n与小写明文;每个字母循环后移n位,输出密文。

查看原题说明

题目描述凯撒密码是古罗马凯撒大帝用来对军事情报进行加密的算法。简单说来:它采用了替换方式来加密。对信息中的每一个英文字母,循环替换为字母表中该字母后面第n个字母。给定全由小写字母组成的明文串和一个整数n,输出其对应的凯撒密码。输入格式两行。第一行含有一个整数 n, 第二行为需要加密的字母串。输出格式一行,是所求的密码。

输入示例
1
qwe
输出示例
rxf

2. 相关知识

本题用到的写法含义 / 用法
ord(c)-ord("a")字符→0至25的下标
(index+n)%26位移并绕回字母表
chr(index+ord("a"))下标→字符
3. 参考答案
n = int(input())
s = input()
res = ''
for c in s:
   a = chr((ord(c) + n - ord('a')) % 26 + ord('a'))
   res += a
print(res)

方法归纳:所有循环字母替换都用“减起点→移位→取模→加回”。

易错点:不能直接chr(ord(c)+n):越过z后必须绕回a。

P26 大写凯撒解密

输入代码并练习

1. 题目要求

读非空密文(≤200字符);大写字母前移5位解密,其他字符保留。

查看原题说明

题目描述Julius Caesar 曾经使用过一种很简单的密码。对于明文中的每个字符,将它用它字母表中后5位对应的字母来代替(若超过了最后一个字母,则又从头开始)。比如字符A用F来代替,Z用E代替。你的任务是对给定的密文进行解密(还原)得到明文。你需要注意的是:密文中出现的字母都是大写字母。密文中也包括非字母的字符,对这些字符不用进行解码。输入格式一行,代表密文,密文中的字符数不超过200,且一定不为0。输出格式一行,即还原后的明文。

输入示例
C58!QXT?
输出示例
X58!LSO?

2. 相关知识

本题用到的写法含义 / 用法
"A"<=c<="Z"先筛选需要变换的字符
ord(c)-ord("A")-5解密方向与加密相反
chr(index%26+ord("A"))取模后转回大写字母
3. 参考答案
s = input()
ans = ''
for c in s:
   if 'A' <= c <= 'Z':
       ans += chr((ord(c) - ord('A') - 5) % 26 + ord('A'))
   else:
       ans += c
print(ans)

方法归纳:与凯撒加密同模板:换起点A、位移−5,并保留非字母。

P27 亲朋字符串

输入代码并练习

1. 题目要求

读长度2—100、字符ASCII≤63的串;相邻码点和转为新字符,末尾与首字符相邻。

查看原题说明

题目描述编写程序,求给定字符串 s 的亲朋字符串s1。亲朋字符串s1的 定义如下:给定字符串s 的第一个字符的 ASCII 值加第二个字符的ASCII 值,得到第一个亲朋字符:给定字符串s 的第二个字符的 ASCII 值加第三个字符的 ASCII 值,得到第二个亲朋字符;依此类准,直到给定字符串 s的倒数第二个字符。亲朋字符串的最后一个字符由给定字符串 s 的最后一个字符 ASCII值加s 的第一个字符的 ASCII 值。输入格式输入一行,一个长度大于等于 2 ,小于等于 100 的字符串。字符串中每个字符的ASCII 值不大于 63 。输出格式输出一行,为变换后的亲朋字符串。输入保证变换后的字符串只有一行。

输入示例
1234
输出示例
cege

2. 相关知识

本题用到的写法含义 / 用法
ord(s[i])+ord(s[i+1])相邻两个字符→两个数相加
chr(sum_value)整数码点→新字符
ord(s[-1])+ord(s[0])单独处理首尾相连
3. 参考答案
s = input()
ans = ''
for i in range(len(s) - 1):
   ans += chr(ord(s[i]) + ord(s[i + 1]))
ans += chr(ord(s[-1]) + ord(s[0]))
print(ans)

方法归纳:线性相邻处理与环形边界分别计算,最后一个字符与第一个配对。

易错点:不是拼接两个字符,也不是把数字字符先转int。

P28 药品名规范化

输入代码并练习

1. 题目要求

读n(≤100),再读n个药名(≤20字符);首字符若为字母则大写,其余小写。

查看原题说明

题目描述医生在书写药品名的时候经常不注意大小写,格式比较混乱。现要求你写一个程序将医生书写混乱的药品名整理成统一规范的格式,即药品名的第一个字符如果是字母要大写,其他字母小写。如将 "ASPIRIN"、"aspirin"整理成 "Aspirin"。输入格式第一行一个数字 n, 表示有 n 个药品名要整理,n不超过 100 。接下来n行,每行一个单词,长度不超过 20 ,表示医生手书的药品名。药品名由字母、数字和-组成。输出格式n行,每行一个单词,对应输入的药品名的规范写法。

输入示例
4
AspiRin
cisapride
2-PENICILLIN
Cefradine-6
输出示例
Aspirin
Cisapride
2-penicillin
Cefradine-6

2. 相关知识

本题用到的写法含义 / 用法
s[0].upper()只处理首字符
s[1:].lower()其余部分全部小写
等价简写s.capitalize()
3. 参考答案
n = int(input())
for i in range(n):
   s = input()
   ans = s[0].upper() + s[1:].lower()
   print(ans)

方法归纳:文本规范化先划分“首字符”和“剩余部分”。

易错点:2-PENICILLIN→2-penicillin;不是每个词或连字符后都大写。

P29 大小写互换

输入代码并练习

1. 题目要求

读一整行字符串;大小写互换,数字、空格、标点保持。

查看原题说明

题目描述读入一个字符串,将其中的大写字母变成小写字母,小写字母变成大写字母,其余字母保持不变。输入格式一行,一个字符串。输出格式一行,变换后的字符串。

输入示例
Ask 110 for HELP!
输出示例
aSK 110 FOR help!

2. 相关知识

本题用到的写法含义 / 用法
ASCII大写→小写chr(ord(c)+32)
ASCII小写→大写chr(ord(c)-32)
方法写法s.swapcase()
3. 参考答案
# 解法1:
s = input()
ans = ''
for c in s:
   if 'A' <= c <= 'Z':
       ans += chr(ord(c) + 32)
   elif 'a' <= c <= 'z':
       ans += chr(ord(c) - 32)
   else:
       ans += c
print(ans)

方法归纳:先分类再转换,未匹配字符走else原样保留。

易错点:±32只用于ASCII英文字母,不能推广到全部Unicode字符。

P30 两侧等量填充

输入代码并练习

1. 题目要求

读n和单字符c,再读串s;用center使s两侧各补n个c。

查看原题说明

题目描述对于一个字符串s,  让它以一定的长度居中输出:两侧各填充n个指定的字符c。输入格式两行。第一行为一个整数n和一个字符c,用空格隔开;第二行为一个字符串s。输出格式使用字符串的center方法得到所要格式的字符串并输出。

输入示例
4 *
hello
输出示例
****hello****

2. 相关知识

本题用到的写法含义 / 用法
len(s)+2*n总宽=原长+两侧填充
s.center(width,c)c必须单字符
3. 参考答案
n,  c = input().split()
n = int(n)
s = input()
print(s.center(n*2+len(s), c))

方法归纳:宽度题先判断参数表示“总宽”还是“每侧增加量”。

易错点:本题要求center;拼接虽能得到同样输出,未满足方法要求。

P31 单词长度序列

输入代码并练习

1. 题目要求

读一行1—300个词(总长≤1000);按空白分词,输出各词长度,以逗号分隔。

查看原题说明

题目描述输入一行单词序列,相邻单词之间由 1 个或多个空格间隔,请对应地计算各个单词的长度。注意,如果有标点符号(如连字符,逗号,句号),标点符号算作与之相连的词的一部分。没有被空格间隔开的符号串,都算作单词。输入格式一行单词序列,最少 1 个单词,最多 300 个单词,单词之间用至少 1个空格间隔。单词序列总长度不超过 1000 。输出格式依次输出对应单词的长度,之间以逗号间隔。

输入示例
She was born in 1990-01-02  and  from Beijing city.
输出示例
3,3,4,2,10,3,4,7,5

2. 相关知识

本题用到的写法含义 / 用法
input().split()合并多个连续空格
len(word)相连标点也算词的一部分
ans[:-1]删掉累计末尾的多余逗号
3. 参考答案
words = input().split()
ans = ''
for word in words:
   ans += str(len(word)) + ','
print(ans[:-1])

方法归纳:分词→逐词映射长度→带分隔符输出;也可用join一次连接。

易错点:只一个词时也要正常输出,不能多出逗号。

P32 忽略空格和大小写比较

输入代码并练习

1. 题目要求

读两行(各≤100字符);忽略空格和大小写,相同输出YES,否则NO。

查看原题说明

题目描述判断两个由大小写字母和空格组成的字符串在忽略大小写,且忽略空格后是否相等。输入格式两行,每行包含一个字符串;字符串长度不超过 100 。输出格式若两个字符串相等,输出 "YES",否则输出"NO"。

输入示例
a A bb BB ccc CCC
Aa BBbb CCCccc
输出示例
YES

2. 相关知识

本题用到的写法含义 / 用法
replace(" ","")删除所有普通空格
upper()统一大小写;lower也可
s1 == s2规范化后再比较
3. 参考答案
s1 = input()
s2 = input()
s1 = s1.replace(' ', '').upper()
s2 = s2.replace(' ', '').upper()
if s1 == s2:
   print('YES')
else:
    print('NO')

方法归纳:把“忽略某差异”改成“先做同样的规范化”。

易错点:strip只删首尾,不能去掉中间空格。末行NO已跨页补回。

P33 死亡率格式化

输入代码并练习

1. 题目要求

输入确诊数m与死亡数n;输出死亡比例,百分数固定3位小数。

查看原题说明

题目描述小药丸最近研究甲流,发现:甲流并不可怕。在中国,它的死亡率并不是很高。请根据截止 2009 年 12 月 22 日各省报告的甲流确诊数和死亡数,计算甲流在各省的死亡率。输入格式输入仅一行,有两个整数,第一个为确诊数,第二个为死亡数,都在[1, 20000 ]范围内。输出格式输出仅一行,甲流死亡率,以百分数形式输出,精确到小数点后 3 位。

输入示例
10433 60
输出示例
0.575%

2. 相关知识

本题用到的写法含义 / 用法
ratio = n/m分子死亡数,分母确诊数
f"{ratio:.3%}"自动×100并补%
3. 参考答案
m, n = map(int, input().split())
ans = n / m
print(f'{ans:.3%}')

方法归纳:比例题先算0—1尺度,再用百分比格式输出。

易错点:不应写成f"{ratio*100:.3%}",否则重复乘100。

P34 圆的直径周长面积

输入代码并练习

1. 题目要求

输入半径r(0<r≤10000);π=3.14159,输出直径、周长、面积,各4位小数。

查看原题说明

题目描述给出圆的半径,求圆的直径、周长和面积。如果圆的半径是 r,  那么圆的直径、周长、面积分别是 2r 、2πr、πr ,其中约定 π= 3.14159。输入格式输入包含一个实数 r ( 0 < r ≤ 10000 ),表示圆的半径。输出格式输出一行,包含三个数,分别表示圆的直径、周长、面积,数与数之间以一个空格分开,每个数保留4位小数。

输入示例
3.0
输出示例
6.0000 18.8495 28.2743

2. 相关知识

本题用到的写法含义 / 用法
2*r / 2*pi*r / pi*r*r直径 / 周长 / 面积
f"{d:.4f} {p:.4f} {a:.4f}"一串中多个占位槽,各自控制精度
3. 参考答案
r = float(input())
pi = 3.14159
diameter = 2 * r
perimeter = 2 * pi * r
area = pi * r * r
print(f'{diameter:.4f} {perimeter:.4f} {area:.4f}')

方法归纳:一次输出多个结果:每个变量都单独指定格式。

易错点:中间空格写在f串里;不是只格式化第一个变量。

P35 加密的病历单

输入代码并练习

1. 题目要求

读长度<50的大小写字母串;各字母右移3位→整串逆序→大小写互换。

查看原题说明

输入长度小于50、仅含大小写字母的字符串。先在各自字母表内循环右移3位,再逆序,最后大小写互换,输出密文。

输入示例
abz
输出示例
CED

2. 相关知识

本题用到的写法含义 / 用法
ord/chr + %26分别在A—Z或a—z内循环移位
ans[::-1]整串逆序,不是取最后一位
.swapcase()逆序结果再大小写互换
3. 参考答案
s = input()
ans = ''
for c in s:
    if c.isupper():
        c = chr((ord(c) - ord('A') + 3) % 26 + ord('A'))
    elif c.islower():
        c = chr((ord(c) - ord('a') + 3) % 26 + ord('a'))
    ans += c
print(ans[::-1].swapcase())

方法归纳:复合变换按步骤顺序处理,前一步结果作为后一步输入。

易错点:背景说“解密”,但题面步骤与样例实际要求加密,按三步执行。

P36 去掉dis前缀与ing后缀

输入代码并练习

1. 题目要求

输入n,随后n个单词;若有dis前缀、ing后缀,分别去掉后输出。

查看原题说明

第一行输入n,随后n行各一个单词;删除开头dis和末尾ing,两者可能同时存在,其他内容保留。

输入示例
4
discover
disliking
jumping
does
输出示例
cover
lik
jump
does

2. 相关知识

本题用到的写法含义 / 用法
startswith("dis") + s[3:]判前缀后删前3个
endswith("ing") + s[:-3]判后缀后删后3个
3. 参考答案
n = int(input())
for i in range(n):
    s = input()
    if s.startswith('dis'):
        s = s[3:]
    if s.endswith('ing'):
        s = s[:-3]
    print(s)

方法归纳:前后缀可同时有→用两个独立if,而非if/elif。

易错点:removeprefix/removesuffix也可;strip不按完整前后缀删除。

P37 日期整理

输入代码并练习

1. 题目要求

读日期数n,随后每行年、月、日;输出YYYY-MM-DD。

查看原题说明

输入n,随后n行各有以空格分隔的年、月、日,整理为四位年-两位月-两位日。

输入示例
3
865 3 12
1900 11 3
2023 10 25
输出示例
0865-03-12
1900-11-03
2023-10-25

2. 相关知识

本题用到的写法含义 / 用法
zfill(4) / zfill(2)年补4位,月日补2位
f串等价写法f"{y:04d}-{m:02d}-{d:02d}"
3. 参考答案
n = int(input())
for i in range(n):
    parts = input().split()
    s = parts[0].zfill(4) + '-' + parts[1].zfill(2) + '-' + parts[2].zfill(2)
    print(s)

方法归纳:定宽编号、日期、流水号都用“宽度+补0”。

易错点:f串d格式要求整数;zfill作用于字符串。不校验日期合法性。

P38 过滤多余空格

输入代码并练习

1. 题目要求

读≤200字符句子;把单词间多个空格合成一个。

查看原题说明

输入一行长度不超过200的句子,首尾没有空格;将单词之间连续多个空格合为一个。

输入示例
Hello   world.This  is c language.
输出示例
Hello world.This is c language.

2. 相关知识

本题用到的写法含义 / 用法
s.split()按连续空白拆成词
" ".join(words)用一个空格重新连接
3. 参考答案
s = input()
print(' '.join(s.split()))

方法归纳:需要统一分隔符时,用“拆开→重连”,不用反复replace双空格。

5 条件判断与分类

专题方法

条件与分类

要点方法
逻辑关系且and,或or;特别注意等号
分支顺序先特殊再一般;elif链只进入一段
计数输出符合条件时计数/输出,循环后给汇总

P39 区间内17的倍数之和

输入代码并练习

1. 题目要求

输入0<m<n<1000;求闭区间[m,n]内17的倍数之和。

查看原题说明

题目描述给定两个正整数m和n,计算m和n之间(包括m和n)能被17整除的数累加的结果是多少。其中,0<m<n<1000。输入格式一行,两个用空格隔开的正整数,分别表示m和n。输出格式一行,一个正整数,代表累加和。

输入示例
50 85
输出示例
204

2. 相关知识

本题用到的写法含义 / 用法
range(m,n+1)包含右端n
i % 17 == 0判断17的倍数
ans += i累加数值,不是累加个数
3. 参考答案
m, n = map(int, input().split())
ans = 0
for i in range(m, n + 1):
   if i % 17 == 0:
       ans += i
print(ans)

方法归纳:区间筛选求和=遍历+取余条件+累加;改17即可迁移到其他倍数。

P40 甲流初筛

输入代码并练习

1. 题目要求

读病人数n(1—200),每行姓名、体温、咳嗽标记;筛出体温≥37.5且标记1者,按序输出姓名及总人数。

查看原题说明

题目描述目前正是甲流盛行时期,为了更好地进行分流治疗,医院在挂号时要求对病人的体温和咳嗽情况进行检查,对于体温超过 37.5 度(含等于 37.5 度)并且咳嗽的病人初步判定为甲流病人(初筛)。现需要统计某天前来挂号就诊的病人中有多少人被初筛为甲流病人。输入格式第一行是某天前来挂号就诊的病人数n,1≤n≤200。其后有n行,每行是病人的信息,包括三个信息:姓名(字符串,不含空格,最多 8 个字符)、体温(在[ 36.0,40.0]范围内、是否咳嗽(1 表示咳嗽,0 表示不咳嗽)。每行三个信息之间以一个空格分开。输出格式按输入顺序依次输出所有被筛选为甲流的病人的姓名,每个名字占一行。之后再输出一行,表示被筛选为甲流的病人数量。

输入示例
5
Zhang 38.3 0
Li 37.5 1
Wang 37.1 1
Zhao 39.0 1
Liu 38.2 1
输出示例
Li
Zhao
Liu
3

2. 相关知识

本题用到的写法含义 / 用法
name,temp,cough=input().split()先按文本拆三项
float(temp)>=37.5 and float(cough)==1两个条件必须同时成立
cnt+=1 + print(name)命中时计数并立即输出
3. 参考答案
n = int(input())
cnt = 0
for i in range(n):
   name, temp, cough = input().split()
   if float(temp)>=37.5 and float(cough)==1:
       cnt+=1
       print(name)
print(cnt)

方法归纳:混合类型输入→只转换需要数值判断的字段→筛选与计数同步。

易错点:37.5含等号;提交里36—40的条件错误,采用老师条件。

P41 闰年判断

输入代码并练习

1. 题目要求

输入年份0<y<3000;闰年输出Y,否则N。

查看原题说明

题目描述公历纪年法中,能被 4 整除的大多是闰年,但能被 100 整除而不能被 400 整除的年份不是闰年,如 1900 年是平年, 2000 年是闰年。输入格式输入只有一行,包含一个整数 a (0 < a < 3000 )。输出格式一行,如果公元 a 年是闰年输出"Y",否则输出"N"。

输入示例
2006
输出示例
N

2. 相关知识

本题用到的写法含义 / 用法
先判%400==0整四百年是闰年
再判%100==0其他整百年是平年
最后判%4==0其余整四年是闰年
3. 参考答案
n = int(input())
if n % 400 == 0:
   print('Y')
elif n % 100 == 0:
   print('N')
elif n % 4 == 0:
   print('Y')
else:
   print('N')

方法归纳:有例外的分类先处理更特殊条件,再处理一般条件。

易错点:1900→N;2000→Y。

P42 年龄分组占比

输入代码并练习

1. 题目要求

读n(1—100)及n个0—100岁年龄;按0—18、19—35、36—60、61以上输出比例,各2位小数百分数。

查看原题说明

题目描述某医院想统计一下某项疾病的获得与否与年齡是否有关,要对以前的诊断记录进行整理按照 0—18 、 19—35 、 36—60 、 61 以上(含 61 )四个年龄段统计的患病人数占总患病人数的比例。输入格式共 2 行,第一行为过往病人的数目n(0 <n≤100),第二行为每个病人患病时的年齡,年齡为不超过 100 的非负整数。输出格式按照0—18 、 19—35 、 36—60 、 61 以上(含 61 )四个年龄段输出该段患病人数占总患病人数的比例,以百分比的形式输出,精确到小数后两位。每个年龄段占一行,共四行。

输入示例
10
1 11 21 31 41 51 61 71 81 91
输出示例
20.00%
20.00%
20.00%
40.00%

2. 相关知识

本题用到的写法含义 / 用法
if <=18; elif <=35; elif <=60; else分支互斥,边界不漏
count/n各组人数÷总人数
f"{count/n:.2%}"百分数2位小数
3. 参考答案
n = int(input())
ages = list(map(int, input().split()))
a = b = c = d = 0  # 分别表示四个年龄段的人数
for age in ages:
   if age <= 18:
       a += 1
   elif age <= 35:
       b += 1
   elif age <= 60:
       c += 1
   else:
       d += 1
for count in (a, b, c, d):
    print(f'{count / n:.2%}')

方法归纳:分类计数→统一分母→同一格式依次输出。

易错点:老师页只显示计数,四行比例输出为整理者补全。

P43 删除指定后缀

输入代码并练习

1. 题目要求

读一个≤32字符单词;若结尾是er、ly或ing,删除一次该后缀,否则原样输出。

查看原题说明

题目描述给定一个单词,如果该单词以er、ly 或者 ing 后缀结尾,则删除该后缀(题目保证删除后缀后的单词长度不为 0),否则不进行任何操作。输入格式输入一行,包含一个单词(单词中间没有空格,每个单词最大长度为 32 )。输出格式输出按照题目要求处理后的单词。

输入示例
referer
输出示例
refer

2. 相关知识

本题用到的写法含义 / 用法
endswith("er") / endswith("ly")命中删后2个:s[:-2]
endswith("ing")命中删后3个:s[:-3]
3. 参考答案
a = input()
if a.endswith('er') or a.endswith('ly'):
   print(a[:-2])
elif a.endswith('ing'):
   print(a[:-3])
else:
   print(a)

方法归纳:同长度后缀合并判断;不同长度分别切片。

易错点:只删末尾的一种后缀,不删除中间出现的子串。

6 循环与综合算法

专题方法

循环、枚举与模拟

要点方法
循环状态初值→本轮操作→更新→终止
枚举缩范围→用等式消元→检查复杂度
组合判定素数/回文等先做独立判定,再组合

P44 最高成绩

输入代码并练习

1. 题目要求

读人数n(1—100),再读n个0—100分成绩;输出最高分。

查看原题说明

题目描述A老师讲授的《计算概论》这门课中考试刚刚结束,他想知道考试中取得的最高分数。因为人数比较多,他觉得这件事情交给计算机来做比较方便。输入格式输入两行,第一行为整数n(1≤n ≤100),表示参加这次考试的人数。第二行是这n个学生的成绩,相邻两个数之间用单个空格隔开。所有成绩均为 0 到100 之间的整数。输出格式一个整数,即最高的成绩。

输入示例
5
85 78 90 99 60
输出示例
99

2. 相关知识

本题用到的写法含义 / 用法
list(map(int,input().split()))成绩文本→整数列表
max(scores)取列表最大元素
3. 参考答案
n = int(input())
scores = list(map(int, input().split()))
print(max(scores))

方法归纳:多个数据先转对类型再比较;循环版可维护当前最大值。

易错点:字符串比较会把"9"看得比"80"大;先转int。

P45 九九乘法表

输入代码并练习

1. 题目要求

无输入;输出下三角九九乘法表,乘积宽2右对齐。

查看原题说明

题目描述请在屏幕上打印出如样例所示的九九乘法表。

2. 相关知识

本题用到的写法含义 / 用法
i=1…9,j=1…i外层行,内层该行的算式
f"{j}*{i}={i*j:2}"花括号可放表达式;:2最小宽2
end=" " + print()行内接排,行末换行
3. 参考答案
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f'{j}*{i}={i * j:2}', end=' ')
    print()

方法归纳:表格输出先确定行列范围,再用最小宽度对齐字段。

P46 百钱买百鸡:枚举解

输入代码并练习

1. 题目要求

输入n(1—200);n文买n只鸡:公鸡5文,母鸡3文,小鸡3只1文;按公鸡、母鸡枚举次序输出全部非负解,无解输出No Answer.。

查看原题说明

题目描述百钱买百鸡问题:公鸡五文钱一只,母鸡三文钱一只,小鸡三只一文钱,用 100文钱买 100 只鸡,公鸡、母鸡、小鸡各买多少只?本程序要求解的问题是:给定一个正整数 n, 用n文钱买n只鸡,问公鸡、母鸡、小鸡各买多少只?输入格式一行,一个正整数n,1≤ n ≤ 200。输出格式如果有解,依次输出公鸡、母鸡、小鸡的个数(用非负整数表示)。如果无解,输出 "No Answer."

输入示例
100
输出示例
0 25 75
4 18 78
8 11 81
12 4 84

2. 相关知识

本题用到的写法含义 / 用法
chick=n-cock-hen总数约束消去第三个循环
chick%3==0小鸡须每3只为一组
flag=False,找到后置True循环结束判断是否无解
3. 参考答案
n = int(input())
flag = False
for cock in range(n // 5 + 1):
    for hen in range(n // 3 + 1):
        chick = n - cock - hen
        if (chick >= 0 and chick % 3 == 0
                and 5 * cock + 3 * hen + chick // 3 == n):
            flag = True
            print(cock, hen, chick)
if not flag:
    print('No Answer.')

方法归纳:枚举数量问题先用等式消元,再收紧每个变量范围。

易错点:0只合法;改成>0会漏掉样例第一组解。

P47 百钱买百鸡:解的数量

输入代码并练习

1. 题目要求

百钱买百鸡加强版:1≤n≤10⁸,只输出非负整数解的数量;无解输出No Answer.。

查看原题说明

题目描述百钱买百鸡问题:公鸡五文钱一只,母鸡三文钱一只,小鸡三只一文钱,用 100文钱买 100 只鸡,公鸡、母鸡、小鸡各买多少只?本程序要求解的问题是:给定一个正整数 n, 用n文钱买n只鸡,问公鸡、母鸡、小鸡各买多少只?输入格式一行,一个正整数n,1≤ n ≤ 10^8。输出格式如果有解,则输出有多少种解(公鸡、母鸡、小鸡能用非负整数表示的解)。如果无解,输出 "No Answer."

输入示例
100
输出示例
4

2. 相关知识

本题用到的写法含义 / 用法
7*x+4*y=n由总数与金额两式消元
x0=(-n)%4公鸡数满足x≡−n(mod 4)
x=x0,x0+4,...≤n//7等差序列计数可O(1)求解
3. 参考答案
n = int(input())
cnt = 0
for x in range(n // 7 + 1):
    if (n - 7 * x) % 4 == 0 and (n + x) % 4 == 0:
        cnt += 1
print(cnt if cnt else 'No Answer.')

方法归纳:枚举→消元→同余→数等差项;大范围必须检查复杂度。

易错点:课堂O(n)版本保留作推导;完整n≤10⁸优先用下方O(1)整理版。

大范围计数优化

整理者推导,时间复杂度O(1)。

n = int(input())
x0 = (-n) % 4
upper = n // 7
cnt = 0 if x0 > upper else (upper - x0) // 4 + 1
print(cnt if cnt else 'No Answer.')

P48 十进制转二进制

输入代码并练习

1. 题目要求

输入正整数n;输出不带0b前缀的二进制表示。

查看原题说明

题目描述输入一个正整数n,输出其对应的二进制数。输入格式一行,一个正整数n。输出格式一行,一个二进制数。

输入示例
78
输出示例
1001110

2. 相关知识

本题用到的写法含义 / 用法
n%2 / n//=2取最低位 / 去掉最低位
s=str(bit)+s余数要逆序,故放到串前面
内置变式bin(n)[2:]
3. 参考答案
n = int(input())
s = ''
while n:
    s = str(n % 2) + s
    n //= 2
print(s)

方法归纳:十进制转任意b进制:反复除b取余,再逆序(大于9的数位需映射)。

易错点:题目只含正数;若扩展输入0,需单独输出0。

P49 调和级数阈值

输入代码并练习

1. 题目要求

读整数K(1—15);求最小n使1+1/2+…+1/n>K。

查看原题说明

题目描述已知: S = 1 + 1/2 + 1/3 + … + 1/n。显然对于任意一个整数 K,当n足够大的时候,S 大于K。现给出一个整数 K(1≤K≤15),要求计算出一个最小的n;使得S > K输入格式一行,一个正整数,代表K。输出格式一行,一个正整数,代表n。

输入示例
1
输出示例
2

2. 相关知识

本题用到的写法含义 / 用法
n=sn=0从第0项、和0开始
while sn<=k没达到“严格大于”就继续
n+=1; sn+=1/n先更新项号,再加这一项
3. 参考答案
k = int(input())
n = sn = 0
while sn <= k:
    n += 1
    sn += 1 / n
print(n)

方法归纳:最早达到阈值题→维护当前状态,首次达标立即停止。

易错点:不能写sn<k:恰好相等时还没完成目标。

P50 青蛙爬井

输入代码并练习

1. 题目要求

输入high、up、down,1≤down<up≤high≤1000;求青蛙从井底爬出的天数。

查看原题说明

题目描述有一口深度为 high 米的水井,井底有一只青蛙,它每天白天能够沿井壁向上爬up米,夜里则顺井壁向下滑 down 米,若青蛙从某个早晨开始向外爬,对于任意指定的 high 、up和 down 值(均为自然数),计算青蛙多少天能够爬出井口?注意:不能简单地认为每天上升的高度等于白天向上爬的距离减去夜间下滑的距离,因为若白天能爬出井口,则不必等到晚上。输入格式输入 3 个正整数: high 、和 down。数据范围1≤down<up<high≤1000 。输出格式输出一个整数,表示天数。输出单独占一行。

输入示例
10 2 1
输出示例
9

2. 相关知识

本题用到的写法含义 / 用法
days+=1; dis+=up进入新一天并上爬
if dis>=high: break达到井口即结束
dis-=down尚未出井才执行夜间下滑
3. 参考答案
high, up, down = map(int, input().split())
days = dis = 0
while True:
    days += 1
    dis += up
    if dis >= high:
        break
    dis -= down
print(days)

方法归纳:模拟题先列事件时间线,再按顺序更新变量。

易错点:不能直接每天净升up−down;最后一天不下滑。

P51 消费返现天数

输入代码并练习

1. 题目要求

输入M、k(2≤k≤M≤1000);每天花1元,每累计花k元返1元,求可消费天数。

查看原题说明

题目描述小药丸为了实现暑假去云南旅游的梦想,决定以后每天只消费 1 元,每花k元就可以再得到 1 元,一开始小药丸有 M 元,问最多可以坚持多少天。输入格式一行,两个整数,分别表示 M 和 k,  2 ≤ k ≤ M ≤ 1000。输出格式一行,一个整数,表示 M 元可以消费的天数。

输入示例
4 3
输出示例
5

2. 相关知识

本题用到的写法含义 / 用法
days+=1; money-=1先完成当天消费
days%k==0累计消费次数达到k的倍数
money+=1当天完成返现再进入下一轮
3. 参考答案
money, k = map(int, input().split())
days = 0
while money > 0:
    days += 1
    money -= 1
    if days % k == 0:
        money += 1
print(days)

方法归纳:余额与累计消费分开维护;返钱不重置累计天数。

易错点:刚花完钱时也可能获得返现,不能提前退出。

P52 郊区车牌计数

输入代码并练习

1. 题目要求

读N(1—10⁵)个车牌;首字母不在ABCDEFGRST中的计为郊区,输出数量。

查看原题说明

题目描述北京市车管所为每一辆入户的汽车都发放一块车牌,车牌的号码由六个字符组成,如 A99452 、 B88888 等,这个字符串从左边数起的第一个字符为大写英文字母,表示这辆车是属于北京市区内的汽车还是郊区的汽车;后面的五位由数字组成。假定以字母 A、B、C、D、E、F、G、R、S、T开头的表示是市区车牌,而以其他字母开头的表示郊区车牌。车管所把这个任务交给小药丸,请他找出所给出的车牌中有多少辆是北京郊区的汽车。输入格式第 1 行是一个正整数 N( 1≤n≤100000),表示共有 N 个车牌。接下来的 N行,每行是一个车牌号。题目保证给出的车牌不会重复。输出格式一个整数,代表郊区车牌的数量。

输入示例
3
G54672
Q87680
P77771
输出示例
2

2. 相关知识

本题用到的写法含义 / 用法
plate[0]只需首字符
not in "ABCDEFGRST"使用已知市区集合的补集
3. 参考答案
n = int(input())
cnt = 0
for i in range(n):
    plate = input().strip()
    if plate[0] not in 'ABCDEFGRST':
        cnt += 1
print(cnt)

方法归纳:已知市区字母集合时,用not in判断其补集,避免枚举其他字母遗漏。

易错点:回顾提交串漏了I,采用课件补集写法。

P53 素数判断

输入代码并练习

1. 题目要求

输入n≥2;素数输出yes,否则no。

查看原题说明

题目描述输入一个不小于2的正整数n,如果它是素数,则输出yes,否则输出no输入格式一行,一个正整数,代表n。输出格式一行,一个字符串,如果n是素数,则输出"yes",否则输出"no"。

输入示例
23
输出示例
yes

2. 相关知识

本题用到的写法含义 / 用法
试除2到√nrange(2,int(n**0.5)+1)
n%d==0找到非平凡因数→非素数
break一旦找到因数无需继续
3. 参考答案
n = int(input())
flag = True
for i in range(2, int(n ** 0.5) + 1):
    if n % i == 0:
        flag = False
        break
print('yes' if flag else 'no')

方法归纳:因数成对,一方一定≤√n;素数试除不用一直到n−1。

易错点:若扩展任意整数,先排除n<2。

P54 回文素数计数

输入代码并练习

1. 题目要求

读11<n<1000;统计闭区间[11,n]内既是素数又是回文的数。

查看原题说明

题目描述编程计算 11 到n之间(包括n),既是素数又是回文数的整数有多少个。输入格式一个大于 11小于 1000 的整数n。输出格式11 到n之间的素数回文数个数。

输入示例
23
输出示例
1

2. 相关知识

本题用到的写法含义 / 用法
for...else未因break退出→可按素数处理
s=str(i)数字转成字符串
s==s[::-1]逆序切片判回文
3. 参考答案
n = int(input())
cnt = 0
for i in range(11, n + 1):
    for j in range(2, i):
        if i % j == 0:
            break
    else:
        s = str(i)
        if s == s[::-1]:
            cnt += 1
print(cnt)

方法归纳:组合判定:先筛素数,再做回文判断;多个条件可封装成函数。

易错点:不是s[-1];逆序是s[::-1]。计数而非输出各个数。

P55 猴子吃桃

输入代码并练习

1. 题目要求

第n天早晨只剩1个桃子;此前每天吃掉一半再多吃1个,求最初数量。

查看原题说明

输入正整数n,第n天早上剩1个桃子。此前每天吃掉一半再多吃1个,求第一天早上的桃子数。

输入示例
4
输出示例
22

2. 相关知识

本题用到的写法含义 / 用法
p=1从最后一天状态开始
p=2*(p+1)把“减一后折半”的过程反过来
重复n−1次第n天回到第1天需要n−1步
3. 参考答案
n = int(input())
p = 1
for i in range(n - 1, 0, -1):
    p = 2 * (p + 1)
print(p)

方法归纳:已知末状态且正向操作可逆→倒推;先加回额外损失,再乘倍数。

P56 药房管理

输入代码并练习

1. 题目要求

读初始库存m、人数n及按到达顺序的n个需求;不足时拒绝且不扣库存,求拒绝人数。

查看原题说明

第一行库存m,第二行人数n,第三行按顺序给出n个取药数量。库存不足则拒绝且不扣库存;求被拒绝人数。

输入示例
30
6
10 5 20 6 7 8
输出示例
2

2. 相关知识

本题用到的写法含义 / 用法
quantity>stock不足→拒绝计数加1
else: stock-=quantity够用→扣除库存
3. 参考答案
stock = int(input())
n = int(input())
requests = list(map(int, input().split()))
refused = 0
for quantity in requests:
    if quantity > stock:
        refused += 1
    else:
        stock -= quantity
print(refused)

方法归纳:顺序处理资源分配;每个请求都基于更新后的库存。

易错点:拒绝后仍继续:后来的小需求可能满足。代码为题意补写。

P57 棋盘中的正方形与非正方形长方形

输入代码并练习

1. 题目要求

输入1≤N,M≤100的方格棋盘;输出沿网格线的正方形数、非正方形长方形数。

查看原题说明

输入N、M(1至100),统计N行M列方格棋盘中沿网格线构成的正方形、非正方形长方形,依次输出两个数量。

输入示例
2 3
输出示例
8 10

2. 相关知识

本题用到的写法含义 / 用法
边长k的正方形(N-k+1)*(M-k+1)个
宽w、高h的矩形(M-w+1)*(N-h+1)个
if width!=height从长方形统计中排除正方形
3. 参考答案
N, M = map(int, input().split())
squares = rectangles = 0
for size in range(1, min(N, M) + 1):
    squares += (N - size + 1) * (M - size + 1)
for width in range(1, M + 1):
    for height in range(1, N + 1):
        if width != height:
            rectangles += (M - width + 1) * (N - height + 1)
print(squares, rectangles)

方法归纳:先固定尺寸数位置,再对所有尺寸求和。

易错点:第二项“不包括正方形”,不能与第一项重复。

P58 买铅笔

输入代码并练习

1. 题目要求

输入需求n,随后3行各给每包支数q、价格p;仅买一种包装,买够至少n支的最低花费。

查看原题说明

输入至少需要的铅笔数n,随后3行各给一种包装的支数quantity及价格price。只买同一种包装,不拆包,求最低花费。

输入示例
10
3 5
5 8
10 20
输出示例
16

2. 相关知识

本题用到的写法含义 / 用法
(n+q-1)//q正整数除法向上取整
packs*p该包装的总价
min(costs)比较三种独立方案
3. 参考答案
n = int(input())
costs = []
for i in range(3):
    quantity, price = map(int, input().split())
    units_needed = (n + quantity - 1) // quantity
    costs.append(units_needed * price)
print(min(costs))

方法归纳:不可拆包+至少够用→先算包数,再算费用,再取最小。

易错点:不是混合购买三种包装;只比较单种包装方案。

P59 发放金币

输入代码并练习

1. 题目要求

阶段1:1天每天1枚;阶段2:2天每天2枚……读k(1—10000),求前k天金币数。

查看原题说明

第1阶段连续1天每天1枚,第2阶段连续2天每天2枚,依此类推。输入1至10000的k,求前k天金币总数。

输入示例
6
输出示例
14

2. 相关知识

本题用到的写法含义 / 用法
阶段n持续n天,共n*n枚
total_days-k最后阶段多算的天数
n*superfluous_days每个多算日扣掉n枚
3. 参考答案
k = int(input())
total_days = total_coins = n = 0
while total_days < k:
    n += 1
    total_coins += n * n
    total_days += n
superfluous_days = total_days - k
if superfluous_days != 0:
    total_coins -= n * superfluous_days
print(total_coins)

方法归纳:不等长阶段累积:可以整段加,再扣尾段超出部分。

P60 Peter的糖

输入代码并练习

1. 题目要求

输入n颗糖、兑换数k(k>1);每吃1颗得1张糖纸,k张换1颗,求最终吃糖总数。

查看原题说明

输入糖数n及兑换所需糖纸数k(k>1),吃糖后可用k张糖纸换1颗糖,求最终吃到的总糖数。

输入示例
10 3
输出示例
14

2. 相关知识

本题用到的写法含义 / 用法
一次吃k颗并换回1颗剩余可吃数量n=n-k+1
if n<k不足兑换时直接吃掉剩余n颗
O(1)变式n+(n-1)//(k-1)
3. 参考答案
n, k = map(int, input().split())
num = 0
while n > 0:
    if n < k:
        num += n
        break
    num += k
    n = n - k + 1
print(num)

方法归纳:兑换中每增加1颗糖,净消耗k−1张纸;可由模拟推公式。

易错点:不要允许“借糖纸”,那是另一种题意。

P61 猜数字游戏

输入代码并练习

1. 题目要求

随机产生1—100目标;反复猜测,提示大/小,猜中后输出次数。

查看原题说明

随机产生1至100的目标,反复输入猜测,输出猜大或猜小,猜中后输出猜测次数。

2. 相关知识

本题用到的写法含义 / 用法
randint(1,100)目标只生成一次,在循环外
guess=int(input())每轮重新输入,次数加1
if > / elif < / else大 / 小 / 相等→break
3. 参考答案
import random
target = random.randint(1, 100)
count = 0
while True:
    guess = int(input())
    count += 1
    if guess > target:
        print('猜大了')
    elif guess < target:
        print('猜小了')
    else:
        print('猜对了')
        break
print('此轮的猜测次数是:', count)

方法归纳:反复交互=循环读入→比较反馈→终止条件;状态不应在循环中错误重置。

易错点:课件缺少guess输入,整理版已补上。

7 化合物相似度与文件筛选

专题方法

计算指标与筛选对象

要点方法
公式层已知统计量→余弦相似度
提取层原始指纹→a,b,c
筛选层文件候选→算指标→记录最大指标与对象

P62 已知特征数量的化合物余弦相似度

输入代码并练习

1. 题目要求

分3行读a、b、c:两指纹各自1的个数及共同1的个数;输出c/√(ab)。

查看原题说明

分三行输入a、b、c,分别表示两个分子指纹中1的数量及共同为1的数量,输出c/sqrt(a*b)。

输入示例
20
50
10
输出示例
0.31622776601683794

2. 相关知识

本题用到的写法含义 / 用法
(a*b)**0.5平方根
c/(a*b)**0.5二进制向量的余弦相似度
3. 参考答案
a = eval(input())
b = eval(input())
c = eval(input())
cosinesimilarity = c / (a * b) ** 0.5
print(cosinesimilarity)

方法归纳:把数学公式中的每个量对应到输入,再按公式计算。

易错点:要求a*b>0;不应替换为其他相似度公式。

P63 根据两个分子指纹计算余弦相似度

输入代码并练习

1. 题目要求

读两条等长非零0/1指纹;统计各自1数a,b及相同位置共同1数c,输出余弦相似度。

查看原题说明

分两行输入等长的0/1指纹,先统计a、b、c,再输出余弦相似度。

输入示例
111100
101000
输出示例
0.7071067811865475

2. 相关知识

本题用到的写法含义 / 用法
for i in range(len(fpa))按对应位置逐位看
a/b/c三个计数器各自含1 / 共同含1
c/(a*b)**0.5计数结果代入公式
3. 参考答案
fpa = input()
fpb = input()
a = b = c = 0
for i in range(len(fpa)):
    if fpa[i] == '1':
        a += 1
    if fpb[i] == '1':
        b += 1
    if fpa[i] == '1' and fpb[i] == '1':
        c += 1
print(c / (a * b) ** 0.5)

方法归纳:先从原始数据提取统计量,再使用上一题的计算模型。

易错点:全零向量时公式未定义,不能直接除0。

P64 从指纹文件筛选最相似化合物

输入代码并练习

1. 题目要求

输入目标指纹,从compounds.txt逐行候选中找最大余弦相似度,输出该指纹。

查看原题说明

键盘输入目标指纹;compounds.txt每行一个候选指纹;输出相似度最大的候选指纹。

2. 相关知识

本题用到的写法含义 / 用法
with open(...,encoding="utf-8")自动关闭文件;逐行读取
line.strip()去掉行尾换行,得到候选串
if cosine>best: best,ans=cosine,fpb最大值与对应对象一起更新
3. 参考答案
def similarity(fpa, fpb):
    a = fpa.count('1')
    b = fpb.count('1')
    c = 0
    for i in range(len(fpa)):
        if fpa[i] == fpb[i] == '1':
            c += 1
    return c / (a * b) ** 0.5

fpa = input()
maxcosine = -1
ans = None
with open('compounds.txt', 'rt', encoding='utf-8') as fi:
    for line in fi:
        fpb = line.strip()
        cosine = similarity(fpa, fpb)
        if cosine > maxcosine:
            maxcosine = cosine
            ans = fpb
if ans is not None:
    print(ans)

方法归纳:“找最大对象”=提取候选→计算指标→同时记录指标与对象。

易错点:best从−1起;原来设0会在所有相似度为0时漏赋ans。

P65 按CID筛选最相似化合物

输入代码并练习

1. 题目要求

输入目标CID,从cids.txt读取候选CID;调用课件PubChemPy接口转指纹后筛最大相似度。

查看原题说明

输入目标CID;cids.txt中每行一个候选CID。通过课件给定的PubChemPy接口取得指纹,比较后输出最相似CID。

2. 相关知识

本题用到的写法含义 / 用法
Compound.from_cid(cid)课件接口:CID→Compound对象
int(f,16)→bin(...)[2:].zfill(4)十六进制每位转4位二进制
finger_bin[32:-7]沿用课件的前后缀裁切
3. 参考答案
from pubchempy import Compound

def cid_to_fingerprint(cid):
    c = Compound.from_cid(cid)
    finger_hex = c.fingerprint
    finger_bin = ''
    for f in finger_hex:
        finger_bin += bin(int(f, 16))[2:].zfill(4)
    return finger_bin[32:-7]

def similarity(fpa, fpb):
    a = fpa.count('1')
    b = fpb.count('1')
    c = sum(fpa[i] == fpb[i] == '1' for i in range(len(fpa)))
    return c / (a * b) ** 0.5

fpa = cid_to_fingerprint(input())
max_cosine = -1
ans = None
with open('cids.txt', 'rt', encoding='utf-8') as fi:
    for line in fi:
        cid = line.strip()
        fpb = cid_to_fingerprint(cid)
        cosine = similarity(fpa, fpb)
        if cosine > max_cosine:
            max_cosine, ans = cosine, cid
if ans is not None:
    print(ans)

方法归纳:外部接口负责取数据;相似度与最大值筛选仍复用已有函数。

易错点:缺原CID文件,联网格式未实测;不将本地语法通过当成联网通过。

8 课堂应用案例

专题方法

数据解析与状态封装

要点方法
解析原始文本→记录→字段→类型转换
展示用宽度、对齐、精度控制字段
封装固定步骤放函数;数据与状态操作可放类

P66 按序号查找化合物ID与水溶性值

输入代码并练习

1. 题目要求

给定5条定长化合物记录;输入序号01—05,输出相应ID与水溶性。

查看原题说明

使用课件五条定长记录,输入序号01至05,输出相应ID与水溶性值。

输入示例
03
输出示例
the compound ID is: LT-771-216
the solubility value is: 0.03174257

2. 相关知识

本题用到的写法含义 / 用法
int("03") → 3序号转整数;eval("03")会报错
pos=int(sn)*2524字符+换行,占25
s[pos+3:pos+13]定长切片取10字符ID
3. 参考答案
solubilityTxt = (
    'SN,IdentityNo,Solubility\n'
    '01,LT-615-348,0.01971400\n'
    '02,LT-771-215,0.03072346\n'
    '03,LT-771-216,0.03174257\n'
    '04,LT-323-560,0.06074634\n'
    '05,LT-619-512,0.10491267\n'
)
sn = input()
pos = int(sn) * 25
ide = solubilityTxt[pos + 3:pos + 13]
sValue = float(solubilityTxt[pos + 14:pos + 24])
print('the compound ID is:', ide)
print('the solubility value is:', sValue)

方法归纳:固定记录长度→起点=序号×步长;字段按偏移切片。

易错点:数据必须真为定长;已按课件约定重建尾零。

P67 处方内容的格式化展示

输入代码并练习

1. 题目要求

处方名居中宽52;21项顿号分隔文本,每行4项、每项左对齐宽13,行后空一行。

查看原题说明

课件给定处方名与由顿号分隔的21项文本:标题居中于52字符宽度;每行4项,每项左对齐宽13;每行后空一行;最后一项单独显示。

2. 相关知识

本题用到的写法含义 / 用法
find("、") + 切片逐次取出最前一项
f"{herb:<13}"<左对齐,13最小宽度
i%4==0每输出4项后换行
3. 参考答案
fname = '清肺排毒汤'
formula = (
    '麻黄9g、炙甘草6g、杏仁9g、生石膏15~30g(先煎)、桂枝9g、'
    '泽泻9g、猪苓9g、白术9g、茯苓15g、柴胡16g、黄芩6g、姜半夏9g、'
    '生姜9g、紫菀9g、冬花9g、射干9g、细辛6g、山药12g、枳实6g、陈皮6g、藿香9g'
)
print(fname.center(52), '\n')
n = formula.count('、')
remain = formula
for i in range(1, n + 1):
    pos = remain.find('、')
    herb = remain[:pos]
    print(f'{herb:<13}', end='')
    if i % 4 == 0:
        print('\n')
    remain = remain[pos + 1:]
print(remain)

方法归纳:分隔数据→取一项→格式化→按计数换行→更新剩余数据。

易错点:只作课件文本数据;宽度按字符,不保证中文终端显示列等宽。

P68 化合物水溶性数据的格式化输出

输入代码并练习

1. 题目要求

把含英文标题的化合物水溶性文本转为中文表头;ID左宽10,数值右宽12、4位小数。

查看原题说明

给定含标题行的水溶性数据字符串,去掉英文标题并输出中文表头;ID左对齐宽10,数值右对齐宽12、保留4位小数。

2. 相关知识

本题用到的写法含义 / 用法
find("\n") + split(",")先拆一行,再拆两个字段
float(parts[1])小数字符串→数值
"{:<10}{:>12.4f}".format(ide,sol)文本左对齐;数值右对齐+精度
3. 参考答案
s = ('IdentityNo.,Solubility\n'
     'LT-615-348,0.019714\n'
     'LT-771-215,0.03072346\n')
s = s[s.find('LT'):]
print('化合物编号{:>8}'.format('水溶性值'))
while s.find('LT') != -1:
    pos = s.find('\n')
    cp = s[:pos]
    parts = cp.split(',')
    ide = parts[0]
    sol = float(parts[1])
    print('{:<10}{:>12.4f}'.format(ide, sol))
    s = s[pos + 1:]

方法归纳:嵌套分隔:先拆记录,再拆字段,最后逐字段转类型与格式化。

易错点:每轮删除已处理的行;否则无限循环。课件串末尾含换行。

P69 Medicine类与药品库存

输入代码并练习

1. 题目要求

定义Medicine,保存药名、剂量、库存;实现发药与补货,演示库存100→70→120→40。

查看原题说明

定义Medicine类,保存药名、剂量和库存;发药时检查库存,补货时更新库存;演示发30、补50、再发80的过程。

2. 相关知识

本题用到的写法含义 / 用法
__init__ / self.stock初始化 / 当前对象的库存
obj.dispense(q) / obj.restock(q)用方法控制状态改变
f"{quantity}...{self.stock}"f串同时嵌入参数与更新后属性
3. 参考答案
class Medicine:
    def __init__(self, name, dosage, stock):
        self.name = name
        self.dosage = dosage
        self.stock = stock

    def dispense(self, quantity):
        if quantity <= 0:
            print('请输入有效的数量。')
        elif quantity <= self.stock:
            self.stock -= quantity
            print(f'{quantity}颗{self.name}已发放。剩余库存:{self.stock}')
        else:
            print(f'库存不足,无法发放{quantity}颗{self.name}。当前库存:{self.stock}')

    def restock(self, quantity):
        if quantity <= 0:
            print('请输入有效的数量。')
        else:
            self.stock += quantity
            print(f'已成功补充{quantity}颗{self.name}。当前库存:{self.stock}')

painkiller = Medicine('止痛药', '50mg', 100)
print(painkiller.name, painkiller.dosage, painkiller.stock)
painkiller.dispense(30)
painkiller.restock(50)
painkiller.dispense(80)

方法归纳:把相关数据与操作放在类中;每次方法调用都在当前状态上更新。

易错点:先检查q>0与库存足够,合法后再扣;不是先扣再补救。

辗转相除与最大公约数

P70 两个数的最大公约数

输入代码并练习

题目要求

分两行输入两个正整数m、n,输出它们的最大公约数。

函数与语法

函数 / 语法含义与使用条件
def gcd(m, n):定义有两个形参的函数;函数体缩进。
while n:n不为0时继续;n为0时结束。
m % n求余数;除数n必须不为0。
m, n = n, m % n先用旧值计算右侧,再同时更新两个变量。
return abs(m)返回非负结果并结束函数。
gcd(a, b)调用函数;用返回值继续计算或输出。
from math import gcd导入标准库同名函数;结果等价。
参考答案
def gcd(m, n):
    while n:
        m, n = n, m % n
    return abs(m)
m = int(input())
n = int(input())
print(gcd(m, n))

反复将两个数替换为除数和余数;余数为0时得到最大公约数。

P71 五个数的最大公约数

输入代码并练习

题目要求

输入一行五个正整数,以空格分隔;输出它们的最大公约数。

函数与语法

函数 / 语法含义与使用条件
def gcd(m, n):定义有两个形参的函数;函数体缩进。
while n:n不为0时继续;n为0时结束。
m % n求余数;除数n必须不为0。
m, n = n, m % n先用旧值计算右侧,再同时更新两个变量。
return abs(m)返回非负结果并结束函数。
gcd(a, b)调用函数;用返回值继续计算或输出。
from math import gcd导入标准库同名函数;结果等价。
values[1:]切片取第2个至最后一个数。
result = gcd(result, value)将已经求出的公约数与下一个数继续合并。
参考答案
def gcd(m, n):
    while n:
        m, n = n, m % n
    return abs(m)
values = list(map(int, input().split()))
result = values[0]
for value in values[1:]:
    result = gcd(result, value)
print(result)

利用gcd(gcd(a,b),c)=gcd(a,b,c),逐个合并。

P88 最大公约数与最小公倍数

输入代码并练习

题目要求

输入一行两个逗号分隔的正整数m,n。输出格式为:m、n的最大公约数为:g,最小公倍数为:l。

函数与语法

函数 / 语法含义与使用条件
literal_eval(input())解析逗号分隔的数值;不执行输入中的函数或表达式。
x, y = m, n保存原始输入,避免辗转相除后丢失m、n。
while x % y:余数不为0时继续;本题输入保证两个数均为正整数。
x, y = y, x % y同时更新除数和余数。
m * n // gcd两个正整数的最小公倍数等于乘积除以最大公约数。
参考答案
from ast import literal_eval
m, n = literal_eval(input())
x, y = m, n
while x % y:
    x, y = y, x % y
print(f"{m}、{n}的最大公约数为:{y},最小公倍数为:{m*n//y}")

保留原始输入,先求公约数,再用乘积关系求公倍数。

斐波那契与递推数列

P73 斐波那契数列的第n项

输入代码并练习

题目要求

数列前两项均为1,从第3项起每项为前两项之和。输入正整数n(1≤n≤50),输出第n项。

函数与语法

函数 / 语法含义与使用条件
F(1)=F(2)=1项号从1开始;第3项为2。
a = b = 1a、b分别保存相邻两项,初值均为1。
range(n - 1)更新n−1次后,a为第n项;n=1时循环不执行。
a, b = b, a + b同时更新;分别执行两条赋值会错误地使用更新后的a。
return a将第n项返回给调用处;不会自动输出。
print(fib(k), end=" ")输出后用空格分隔;默认end为换行。
print(*values)展开列表中的元素,默认用空格分隔。
参考答案
def fib(n):
    a = b = 1
    for i in range(n - 1):
        a, b = b, a + b
    return a
n = int(input())
print(fib(n))

用两个变量保存相邻项,每轮同时更新。

P74 多组斐波那契数列查询

输入代码并练习

题目要求

输入两行。第一行为查询数量n(1≤n<20);第二行为n个项号k(1≤k≤50),以空格分隔。输出一行,对应各项号的斐波那契数,以空格分隔。

函数与语法

函数 / 语法含义与使用条件
F(1)=F(2)=1项号从1开始;第3项为2。
a = b = 1a、b分别保存相邻两项,初值均为1。
range(n - 1)更新n−1次后,a为第n项;n=1时循环不执行。
a, b = b, a + b同时更新;分别执行两条赋值会错误地使用更新后的a。
return a将第n项返回给调用处;不会自动输出。
print(fib(k), end=" ")输出后用空格分隔;默认end为换行。
print(*values)展开列表中的元素,默认用空格分隔。
list(map(int, input().split()))拆分一行中的多个项号,并分别转为整数。
for k in ls:每轮处理一个查询,不是循环到某一个项号。
参考答案
def fib(n):
    a = b = 1
    for i in range(n - 1):
        a, b = b, a + b
    return a
n = int(input())
ls = list(map(int, input().split()))
for k in ls:
    print(fib(k), end=" ")

把单次计算封装成fib,主程序循环调用;每次调用独立初始化状态。

P75 三项递推数列的第n项

输入代码并练习

题目要求

数列前3项均为1,从第4项起,每一项等于前3项之和。输入正整数n(1≤n≤50),输出第n项。

函数与语法

函数 / 语法含义与使用条件
a = b = c = 1保存相邻三项,前三项初值均为1。
n - 3从第3项继续更新到第n项,需要n−3轮;前三项直接返回1。
a, b, c = b, c, a + b + c同时移动三项并求下一项。
return c最后一个变量保存当前项。
return a将第n项返回给调用处;不会自动输出。
print(fib(k), end=" ")输出后用空格分隔;默认end为换行。
print(*values)展开列表中的元素,默认用空格分隔。
参考答案
def trib(n):
    a = b = c = 1
    for i in range(max(0, n - 3)):
        a, b, c = b, c, a + b + c
    return c

n = int(input())
print(trib(n))

将保存的状态由两项扩展为三项,并调整初值、更新公式和循环次数。

蒙特卡罗法

P77 蒙特卡罗法估算圆周率

输入代码并练习

题目要求

输入一行两个整数n、d,分别为抛点总数和随机种子。设置random.seed(d),每个点依次调用两次random.random()生成x、y,坐标均在[0,1)内。统计x²+y²≤1的点数,输出4*hits/n,保留四位小数。

函数与语法

函数 / 语法含义与使用条件
random.seed(d)使同一种子产生相同的随机序列。
random.random()产生[0,1)内的浮点数;每个点先取x,再取y。
sqrt(x ** 2 + y ** 2) <= 1判断点是否位于单位四分之一圆内;也可直接比较平方和。
4 * hits / n四分之一圆面积占正方形面积的比例约为π/4。
f"{value:.4f}"把数值格式化为小数点后四位。
参考答案
import random
from math import sqrt
n, d = map(int, input().split())
random.seed(d)
hits = 0
for i in range(n):
    x = random.random()
    y = random.random()
    dist = sqrt(x ** 2 + y ** 2)
    if dist <= 1.0:
        hits += 1
print(f"{4 * hits / n:.4f}")

固定同样的采样点后统计圆内点数;可使用等价的距离判断。

P78 蒙特卡罗法估算正弦定积分

输入代码并练习

题目要求

输入一行两个整数n、d,分别为抛点总数和随机种子。设置random.seed(d),每点先取x=3.14*random.random(),再取y=random.random()。统计y≤sin(x)的点数,输出3.14*hits/n,保留四位小数。本题π按3.14计算。

函数与语法

函数 / 语法含义与使用条件
from math import sin导入正弦函数,参数使用弧度。
x = 3.14 * random.random()横坐标位于[0,3.14);不可直接取[0,1)。
y <= sin(x)判断点是否落在曲线下方。
3.14 * hits / n矩形面积乘命中比例,估计积分面积。
f"{value:.4f}"输出小数点后四位。
参考答案
import random
from math import sin
n, d = map(int, input().split())
random.seed(d)
hits = 0
for i in range(n):
    x = 3.14 * random.random()
    y = random.random()
    if y <= sin(x):
        hits += 1
print(f"{3.14 * hits / n:.4f}")

抛点面积法由圆推广到曲线:确定采样矩形、命中条件和面积系数。

异常处理与限次猜数

P89 带异常处理的公约数循环计算

输入代码并练习

题目要求

连续输入逗号分隔的两个数;输入0,0时结束且不输出。两个正整数时按示例输出最大公约数和最小公倍数;数值不是正整数时输出“输入值非法,请重新输入两个正整数!”;解析、解包或其他运行错误时输出“运行有误,请重新输入!”。

函数与语法

函数 / 语法含义与使用条件
literal_eval(input())解析逗号分隔的数值;不执行输入中的函数或表达式。
x, y = m, n保存原始输入,避免辗转相除后丢失m、n。
while x % y:余数不为0时继续;本题输入保证两个数均为正整数。
x, y = y, x % y同时更新除数和余数。
m * n // gcd两个正整数的最小公倍数等于乘积除以最大公约数。
try / except Exception处理输入解析、解包等异常;处理后继续下一轮。
type(m) is int检查确实为整数;不能仅以int(m)==m接受小数。
break检测到0,0时直接结束while。
参考答案
from ast import literal_eval
while True:
    try:
        m, n = literal_eval(input())
        if m == 0 and n == 0:
            break
        if type(m) is int and type(n) is int and m > 0 and n > 0:
            x, y = m, n
            while x % y:
                x, y = y, x % y
            print(f"{m}、{n}的最大公约数为:{y},最小公倍数为:{m*n//y}")
        else:
            print('输入值非法,请重新输入两个正整数!')
    except Exception:
        print('运行有误,请重新输入!')

先检查退出条件,再检查数值类型和范围;异常分支仅负责提示。

P90 限六次的猜数字

输入代码并练习

题目要求

预设随机种子100,用random.randint(0,100)产生目标整数。每次读入一个整数,最多6次。过大输出“您猜的数太大了!”,过小输出“您猜的数太小了!”,猜中按示例输出次数与目标数并结束;6次均未猜中,再输出“很遗憾,您已用完猜数机会!”。

函数与语法

函数 / 语法含义与使用条件
random.seed(100)固定种子;本题randint(0,100)生成的目标数为18。
range(1, 7)最多尝试6次;count也是当前尝试次数。
for ... else未通过break猜中时,循环结束后输出机会用尽。
参考答案
import random
random.seed(100)
target = random.randint(0, 100)
for count in range(1, 7):
    value = int(input())
    if value > target:
        print('您猜的数太大了!')
    elif value < target:
        print('您猜的数太小了!')
    else:
        print(f'恭喜您,{count}次努力后猜中了!这个数字是{target}')
        break
else:
    print('很遗憾,您已用完猜数机会!')

成功时break;循环正常耗尽时由else处理失败。

P91 带输入异常的限次猜数字

输入代码并练习

题目要求

沿用种子100、目标范围0至100及最多6次规则。非数字输入输出“输入有误!”;浮点数输入输出“输入内容必须为整数!”。两类错误均占用一次猜测机会;其余提示、成功和失败格式与限六次猜数字一致。

函数与语法

函数 / 语法含义与使用条件
random.seed(100)固定种子;本题randint(0,100)生成的目标数为18。
range(1, 7)最多尝试6次;count也是当前尝试次数。
for ... else未通过break猜中时,循环结束后输出机会用尽。
except ValueError捕获数字转换失败。
continue本次输入已占用次数,提示后开始下一次。
参考答案
import random
random.seed(100)
target = random.randint(0, 100)
for count in range(1, 7):
    text = input()
    try:
        number = float(text)
    except ValueError:
        print('输入有误!')
        continue
    try:
        value = int(text)
    except ValueError:
        print('输入内容必须为整数!')
        continue
    if value > target:
        print('您猜的数太大了!')
    elif value < target:
        print('您猜的数太小了!')
    else:
        print(f'恭喜您,{count}次努力后猜中了!这个数字是{target}')
        break
else:
    print('很遗憾,您已用完猜数机会!')

把转换异常留在当前轮处理,次数由外层for统一管理。

函数调用与素数应用

P72 用函数判断素数

输入代码并练习

题目要求

输入一个正整数n;若n是素数,输出yes,否则输出no。输入允许为1。

函数与语法

函数 / 语法含义与使用条件
if n < 2: return False负数、0、1均不是素数。
range(2, n)依次试除2至n−1;n=2时为空。
n % i == 0存在非平凡因数,返回False。
return True放在循环之后;所有候选因数均未整除才返回True。
if isprime(n):根据函数返回的布尔值选择分支。
range(2, int(n ** 0.5) + 1)可将试除范围缩小到平方根;须包含平方根。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, n):
        if n % i == 0:
            return False
    return True

n = int(input())
if isprime(n):
    print("yes")
else:
    print("no")

函数只返回判断结果,主程序负责输入和输出。

P79 输出素数对

输入代码并练习

题目要求

输入正整数n(1≤n≤10000)。输出两个数都不大于n、相差为2的全部素数对,按较小数升序输出,每对占一行,以一个空格分隔。没有素数对时输出empty。

函数与语法

函数 / 语法含义与使用条件
n < 21不是素数;先单独排除。
range(2, int(n ** 0.5) + 1)试除至平方根,并包含平方根。
return False找到因数就结束当前函数。
return True必须放在试除循环外。
range(2, n - 1)较小数最大为n−2,因此i+2不会超过n。
found记录是否至少输出过一对,用于处理empty。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True
n = int(input())
found = False
for i in range(2, n - 1):
    if isprime(i) and isprime(i + 2):
        print(i, i + 2)
        found = True
if not found:
    print('empty')

复用素数函数,同时验证i与i+2。

P80 单个偶数的哥德巴赫分解

输入代码并练习

题目要求

输入一个偶数n(4≤n≤100000)。输出n=A+B,其中A、B均为素数;有多个方案时选择A最小的方案。等号和加号两侧不加空格。

函数与语法

函数 / 语法含义与使用条件
n < 21不是素数;先单独排除。
range(2, int(n ** 0.5) + 1)试除至平方根,并包含平方根。
return False找到因数就结束当前函数。
return True必须放在试除循环外。
n - a总和确定后,第二个加数由第一个加数唯一确定。
range(2, n // 2 + 1)从小到大找第一个加数,包含n/2。
return f"{n}={a}+{n-a}"找到第一个解就返回;输出不含空格。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

def goldbach(n):
    for a in range(2, n // 2 + 1):
        if isprime(a) and isprime(n - a):
            return f"{n}={a}+{n-a}"
n = int(input())
print(goldbach(n))

按第一个加数升序枚举,找到素数配对立即返回。

P81 连续偶数的哥德巴赫分解

输入代码并练习

题目要求

输入正偶数N(N≥4)。依次对4至N的所有偶数输出n=A+B,每行一个等式,A为可行方案中最小的第一个加数。

函数与语法

函数 / 语法含义与使用条件
n < 21不是素数;先单独排除。
range(2, int(n ** 0.5) + 1)试除至平方根,并包含平方根。
return False找到因数就结束当前函数。
return True必须放在试除循环外。
n - a总和确定后,第二个加数由第一个加数唯一确定。
range(2, n // 2 + 1)从小到大找第一个加数,包含n/2。
return f"{n}={a}+{n-a}"找到第一个解就返回;输出不含空格。
range(4, N + 1, 2)从4到N遍历偶数,右端加1以包含N。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

def goldbach(n):
    for a in range(2, n // 2 + 1):
        if isprime(a) and isprime(n - a):
            return f"{n}={a}+{n-a}"
N = int(input())
for n in range(4, N + 1, 2):
    print(goldbach(n))

分成两个函数:判断素数、生成一个分解式;主循环处理各偶数。

P82 第n小的质数

输入代码并练习

题目要求

输入一个正整数n(n≤10000),输出按从小到大排序的第n个质数。

函数与语法

函数 / 语法含义与使用条件
n < 21不是素数;先单独排除。
range(2, int(n ** 0.5) + 1)试除至平方根,并包含平方根。
return False找到因数就结束当前函数。
return True必须放在试除循环外。
count, num = 1, 2初始已找到第一个质数2。
while count < n按找到的质数个数停止,而非按候选数停止。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True
n = int(input())
count, num = 1, 2
while count < n:
    num += 1
    if isprime(num):
        count += 1
print(num)

扫描候选整数,只在遇到质数时增加计数。

P83 区间内的素数个数

输入代码并练习

题目要求

输入一行整数X、Y(1≤X,Y≤100000),允许X>Y。输出闭区间[min(X,Y),max(X,Y)]内的素数个数。

函数与语法

函数 / 语法含义与使用条件
n < 21不是素数;先单独排除。
range(2, int(n ** 0.5) + 1)试除至平方根,并包含平方根。
return False找到因数就结束当前函数。
return True必须放在试除循环外。
min(X,Y), max(X,Y)先统一端点顺序。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True
X, Y = map(int, input().split())
count = 0
for num in range(min(X, Y), max(X, Y) + 1):
    if isprime(num):
        count += 1
print(count)

区间遍历与素数函数组合,两个端点都参与统计。

P84 满足数位条件的四位数计数

输入代码并练习

题目要求

输入两行:第一行为四位数个数n(1≤n≤100),第二行为n个四位正整数。统计个位数字减去千位、百位、十位数字之和后大于0的数的个数。

函数与语法

函数 / 语法含义与使用条件
num % 10取个位数字。
num // 10 % 10取十位数字;百位同理。
num // 1000四位数取千位数字。
sum(valid(num) for num in values)True按1、False按0参与求和。
参考答案
def valid(num):
    ones = num % 10
    tens = num // 10 % 10
    hundreds = num // 100 % 10
    thousands = num // 1000
    return ones - thousands - hundreds - tens > 0

n = int(input())
values = list(map(int, input().split()))
print(sum(valid(num) for num in values))

拆出数位,封装条件判断,再统计满足条件的数量。

P85 质数口袋

输入代码并练习

题目要求

输入正整数承重量L。从2开始按升序依次装入质数,累计和不能超过L。逐行输出装入的各质数,最后一行输出装入数量。若一个都不能装入,只输出0。

函数与语法

函数 / 语法含义与使用条件
n < 21不是素数;先单独排除。
range(2, int(n ** 0.5) + 1)试除至平方根,并包含平方根。
return False找到因数就结束当前函数。
return True必须放在试除循环外。
total + num > L加入当前质数前检查是否超载。
break下一个质数已超载,后面更大的质数也不能装入。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True
L = int(input())
total, count, num = 0, 0, 2
while True:
    if isprime(num):
        if total + num > L:
            break
        total += num
        print(num)
        count += 1
    num += 1
print(count)

累计已装入质数的和;停止条件由容量决定。

P86 不小于n的最小素数

输入代码并练习

题目要求

输入正整数n。若n为素数,输出n;否则输出大于n的最小素数。

函数与语法

函数 / 语法含义与使用条件
n < 21不是素数;先单独排除。
range(2, int(n ** 0.5) + 1)试除至平方根,并包含平方根。
return False找到因数就结束当前函数。
return True必须放在试除循环外。
while not isprime(n)当前不是素数时才增加;本身为素数则直接输出。
参考答案
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True
n = int(input())
while not isprime(n):
    n += 1
print(n)

不断测试当前候选数,直到素数判断为真。

P87 Armstrong数判断

输入代码并练习

题目要求

给定一个正整数,若它等于各位数字的位数次方之和,称为Armstrong数。输入一个正整数,满足条件输出YES,否则输出NO。

函数与语法

函数 / 语法含义与使用条件
str(n)把整数转为字符串,便于逐位读取。
len(digits)取得位数,同时作为乘方指数。
int(ch) ** power单个数字的位数次方。
sum(...) == n比较各位乘方之和与原数。
参考答案
n = int(input())
digits = str(n)
power = len(digits)
total = sum(int(ch) ** power for ch in digits)
print('YES' if total == n else 'NO')

由数位遍历生成每一项,再求和判断。

不重复随机数

P76 生成十个不重复的随机整数

输入代码并练习

题目要求

无需输入。生成10个互不相同的整数,范围为10至100(包含两端),在一行中以空格分隔输出。判题只检查数量、范围及互不重复,不要求与示例数值或顺序相同。

函数与语法

函数 / 语法含义与使用条件
random.seed(100)设置随机种子,便于重复观察同一随机过程。
random.randint(10, 100)生成10至100之间的整数,包含两个端点。
len(ls) < 10列表不足10个元素时继续生成。
value not in ls判断本次整数尚未加入列表。
ls.append(value)在列表末尾添加元素;返回值为None。
print(*ls)依次输出列表元素,元素之间用一个空格分隔。
random.sample(range(10, 101), 10)从91个候选整数中无放回抽取10个,也满足本题输出要求。
参考答案
import random
random.seed(100)
ls = []
while len(ls) < 10:
    value = random.randint(10, 100)
    if value not in ls:
        ls.append(value)
print(*ls)

生成一个候选数,先检查是否重复,再加入列表;达到10个后停止。

新增课件分支与循环

P92 批量去掉dis前缀与ing后缀

输入代码并练习

题目要求

输入n及随后n行单词。若单词有dis前缀或ing后缀则去除;二者同时存在时均去除;否则原样输出。大小写敏感,每个结果占一行。

函数与语法

函数 / 语法含义与使用条件
startswith("dis")只检查开头,不删除单词中间的dis。
endswith("ing")只检查末尾。
s[3:-3]两侧各去掉3个字符。
参考答案
n = int(input())
for i in range(n):
    s = input()
    if s.startswith('dis') and s.endswith('ing'):
        s = s[3:-3]
    elif s.startswith('dis'):
        s = s[3:]
    elif s.endswith('ing'):
        s = s[:-3]
    print(s)

先处理两种条件同时成立,再处理单侧条件。

P93 分段销售提成与薪水

输入代码并练习

题目要求

输入整数销售额x(0≤x≤10^9)。基本工资1500元。前10000元按5%提成,超过10000至50000元的部分按10%,超过50000元的部分按15%。输出总工资,保留两位小数。

函数与语法

函数 / 语法含义与使用条件
if / elif / else三个分段互斥,进入一个分支后不再判断后续分支。
sales - 10000只对超出第一档的部分应用10%费率。
f"{value:.2f}"固定输出小数点后两位。
参考答案
sales = int(input())
if sales <= 10000:
    commission = sales * 0.05
elif sales <= 50000:
    commission = 10000 * 0.05 + (sales - 10000) * 0.10
else:
    commission = 10000 * 0.05 + 40000 * 0.10 + (sales - 50000) * 0.15
print(f"{1500 + commission:.2f}")

分段累进:较高档总额由前面各档与当前档的增量共同构成。

P94 改进疗法效果比较

输入代码并练习

题目要求

输入n(1<n≤20),随后n行各含总病例数和有效病例数。第一组为基准,其余为改进疗法。有效率比基准高出超过5个百分点输出better,低出超过5个百分点输出worse,其余输出same。每个改进方案占一行。

函数与语法

函数 / 语法含义与使用条件
b / a基准有效率;应对每个方案使用同一个基准。
d / c - b / a当前方案与基准的百分点差。
20*(d*a-b*c)与a*c比较将0.05阈值比较转成整数比较,避免浮点边界误差。
参考答案
n = int(input())
a, b = map(int, input().split())
for i in range(n - 1):
    c, d = map(int, input().split())
    delta = 20 * (d * a - b * c)
    bound = a * c
    if delta > bound:
        print('better')
    elif delta < -bound:
        print('worse')
    else:
        print('same')

先读基准,随后逐组比较;整数交叉相乘实现精确阈值判断。

P95 连续正常血压的最长时长

输入代码并练习

题目要求

输入n(1≤n<100),随后n行分别给出每小时的收缩压和舒张压。收缩压90至140且舒张压60至90(均包含端点)视为正常。输出连续正常的最长小时数。

函数与语法

函数 / 语法含义与使用条件
90 <= s <= 140 and 60 <= d <= 90两个范围同时满足。
current_hours += 1正常时延长当前连续段。
current_hours = 0异常时清空当前连续段。
max(best, current)保留已经遇到的最长连续段。
参考答案
n = int(input())
current_hours = max_hours = 0
for i in range(n):
    systolic, diastolic = map(int, input().split())
    if 90 <= systolic <= 140 and 60 <= diastolic <= 90:
        current_hours += 1
        max_hours = max(max_hours, current_hours)
    else:
        current_hours = 0
print(max_hours)

同时维护当前连续长度与历史最大长度。

P96 从1到N的整数求和

输入代码并练习

题目要求

输入正整数N,输出1至N(包含两端)的整数之和。

函数与语法

函数 / 语法含义与使用条件
range(1, N + 1)包含1和N。
sumn += i将当前整数加入累计和。
sum(range(1,N+1))等价的内置求和写法。
参考答案
N = int(input())
sumn = 0
for i in range(1, N + 1):
    sumn += i
print(sumn)

初始化累计值为0,逐项相加;也可使用N*(N+1)//2。

P97 筛选7的倍数

输入代码并练习

题目要求

无需输入。逐行输出1至100中能被7整除、但不能被3整除的全部整数。

函数与语法

函数 / 语法含义与使用条件
range(7,101,7)只遍历7的倍数。
i % 3 != 0排除同时为3的倍数的数。
参考答案
for i in range(7, 101, 7):
    if i % 3 != 0:
        print(i)

用步长完成一个条件,再用分支筛选另一个条件。

P98 前十个阶乘之和

输入代码并练习

题目要求

无需输入。计算并输出1!+2!+…+10!。

函数与语法

函数 / 语法含义与使用条件
term *= i把(i−1)!更新为i!,避免重复从头计算。
total += term累计当前阶乘。
参考答案
total, term = 0, 1
for i in range(1, 11):
    term *= i
    total += term
print(total)

保存上一个阶乘作为状态,每轮只做一次乘法。

P99 输出五行数字方阵

输入代码并练习

题目要求

无需输入。输出五行,每行五个数,第i行第j列为10*i+j(i、j均从1到5),同一行以空格分隔。

函数与语法

函数 / 语法含义与使用条件
for i与for j外层决定行,内层决定列。
print(..., end=" ")同一行内以空格分隔。
内层循环后print()一行结束后换行。
参考答案
for i in range(1, 6):
    for j in range(1, 6):
        print(i * 10 + j, end=" ")
    print()

把行列位置映射为对应的数,输出控制分成行内与行末。

P100 表达式的括号匹配

输入代码并练习

题目要求

输入一个长度不超过2000、仅含圆括号、加减号和数字的表达式。圆括号正确匹配输出YES,否则输出NO。

函数与语法

函数 / 语法含义与使用条件
balance += 1遇到左括号,增加尚未闭合的数量。
balance -= 1遇到右括号,消耗一个左括号。
balance < 0某个前缀的右括号过多,立即判定不匹配。
balance == 0扫描结束时不能有未闭合的左括号。
参考答案
s = input()
balance = 0
valid = True
for ch in s:
    if ch == '(':
        balance += 1
    elif ch == ')':
        balance -= 1
        if balance < 0:
            valid = False
            break
print('YES' if valid and balance == 0 else 'NO')

正确匹配既要求数量相同,也要求任何前缀的右括号不多于左括号。

P101 百分制成绩转换为等级

输入代码并练习

题目要求

输入一个数值成绩。90至100为A,80至不足90为B,70至不足80为C,60至不足70为D,0至不足60为E。输入超出0至100时输出“输入错误!需要输入一个在0-100之间的数字!”,否则只输出等级字母。

函数与语法

函数 / 语法含义与使用条件
0 <= score <= 100输入有效性的范围判断。
从高到低的elif前一条件不满足后,后续分支无需重复写上界。
参考答案
score = float(input())
if not 0 <= score <= 100:
    print('输入错误!需要输入一个在0-100之间的数字!')
elif score >= 90:
    print('A')
elif score >= 80:
    print('B')
elif score >= 70:
    print('C')
elif score >= 60:
    print('D')
else:
    print('E')

先排除非法范围,再按阈值从高到低分级。

P102 按指定方式对齐字符串

输入代码并练习

题目要求

输入“左”“中”“右”之一。以星号填充,将字符串python按指定方向在30字符宽度中输出。

函数与语法

函数 / 语法含义与使用条件
<、^、>分别表示左对齐、居中和右对齐。
*填充字符,不是乘法。
f"{text:*{align}30}"在格式说明中嵌入对齐方式变量。
参考答案
mode = input()
if mode == '左':
    align = '<'
elif mode == '中':
    align = '^'
else:
    align = '>'
print(f"{'python':*{align}30}")

先把中文输入映射为格式符,再统一输出。

P103 BMI双标准分级

输入代码并练习

题目要求

课堂数据处理练习。输入一行身高(米)和体重(千克),以逗号分隔,均为正数。BMI=体重/身高²。先输出BMI(两位小数),再输出两套课程标准的分类,以空格分隔。两套标准下限均为18.5;正常范围上限分别为25、24;肥胖前期上限分别为30、28;达到上限进入下一类。分类用“体重过低”“正常范围”“肥胖前期”“肥胖”。

函数与语法

函数 / 语法含义与使用条件
weight / height ** 2先乘方再做除法。
合并阈值18.5、24、25、28、30按两套阈值的并集分段,同时确定两个分类。
f"{bmi:.2f}"只在输出时保留两位,分类使用原始值。
参考答案
height, weight = map(float, input().split(','))
bmi = weight / height ** 2
if bmi < 18.5:
    who, gb = '体重过低', '体重过低'
elif bmi < 24:
    who, gb = '正常范围', '正常范围'
elif bmi < 25:
    who, gb = '正常范围', '肥胖前期'
elif bmi < 28:
    who, gb = '肥胖前期', '肥胖前期'
elif bmi < 30:
    who, gb = '肥胖前期', '肥胖'
else:
    who, gb = '肥胖', '肥胖'
print(f'{bmi:.2f}')
print(who, gb)

多套阈值可以分开判断,也可以按合并后的阈值一次分段。

P104 按类别选择区间阈值

输入代码并练习

题目要求

课堂分支练习。分两行输入性别“男”或“女”和一个数值。课程示例中男的正常区间为[54,106],女为[44,97]。低于对应下限输出“偏低”,在闭区间内输出“正常”,高于上限输出“偏高”。

函数与语法

函数 / 语法含义与使用条件
外层类别判断按性别确定对应的上下限。
value < low与value <= high分别处理低于下限和处于正常区间的情况。
参考答案
gender = input()
value = float(input())
if gender == '男':
    low, high = 54, 106
else:
    low, high = 44, 97
if value < low:
    print('偏低')
elif value <= high:
    print('正常')
else:
    print('偏高')

先选择阈值,再共享同一套区间判断。

P105 按LD50值进行课堂分级

输入代码并练习

题目要求

课堂分支练习。输入非负数LD50,按课程程序采用的阈值输出等级:LD50≥5000为“1级微毒”,500≤LD50<5000为“2级低毒”,50≤LD50<500为“3级中等毒”,1≤LD50<50为“4级高毒”,不足1为“5级剧毒”。

函数与语法

函数 / 语法含义与使用条件
if value >= 5000按阈值从高到低判断。
elif value >= 500该分支实际区间为500至不足5000。
参考答案
value = float(input())
if value >= 5000:
    degree = '1级微毒'
elif value >= 500:
    degree = '2级低毒'
elif value >= 50:
    degree = '3级中等毒'
elif value >= 1:
    degree = '4级高毒'
else:
    degree = '5级剧毒'
print(degree)

用互斥的多分支映射区间与等级。

P106 线性关系函数的调用

输入代码并练习

题目要求

课堂函数练习。定义f(x)=0.8*x+3.25;无需输入,分别计算x=2和x=3时的值,每行一个结果,保留两位小数。

函数与语法

函数 / 语法含义与使用条件
def linearregression(x):把计算关系封装为一个参数的函数。
return 0.8*x+3.25返回计算结果,调用处决定如何输出。
不同实参调用同一函数重复使用函数而不重复公式。
参考答案
def linearregression(x):
    return 0.8 * x + 3.25

print(f'{linearregression(2):.2f}')
print(f'{linearregression(3):.2f}')

把公式放进函数,调用时传入不同数据。

P107 整数奇偶判断

输入代码并练习

题目要求

输入一个整数n。偶数输出“偶数”,奇数输出“奇数”。

函数与语法

函数 / 语法含义与使用条件
n % 2 == 0余数为0表示偶数。
A if condition else B条件为真取A,否则取B。
参考答案
n = int(input())
print("偶数" if n % 2 == 0 else "奇数")

用求余构造布尔条件。