深耕专业教研,探索前沿技术
信息技术来源:2025学年第二学期精诚联盟高三适应性联考

第 15 题

答案与解析

第(1)小题

参考答案

4,6

系统省略每次连续跑步的最后一次打卡,因此记录中的每个编号k都表示已跑过k至k+1的路段。判断是否完成任务,只需检查1—2、2—3、3—4、4—5、5—6五段是否全部覆盖;重复记录不会增加新的覆盖路段。

学生编号 合并后的已完成路段 未完成路段
1 1—4、5—6 4—5
2 1—2、3—6 2—3
3 1—3、4—6 3—4
4 1—6 无
5 1—3、4—6 3—4
6 1—6 无

4号虽然先记录2、3、4、5,再记录1,但这些记录已覆盖全部五段;6号连续记录1至5,也覆盖全部路线。

第(2)小题

参考答案

2

程序分析

res=t[0]*10
p=1; j=1
while j<len(t):
    if t[j]-t[j-1]==p:
        ...
    else:
        ...
    j+=1

res初值的十位是第一条记录,个位为0;j从1开始,检查后续记录。循环中会删除列表元素,因此每轮都按当前列表长度判断,不能按原列表的固定下标逐次推演。

if t[j]-t[j-1]==p:
    res=res//10*10+t[j]
    t.pop(j)
    j-=1
    p+=1

条件成立时,res保留十位的区段起点,把个位改为当前记录;随后删除当前元素,区段起点仍留在t[j-1]的位置。j先减1再由循环末尾加1,使下一条移到此位置的记录仍被检查。

每合入一条连续记录,p加1。例如起点3之后合入4并删除4,下一条应与保留的起点3相差2,而不是与已删除的4相差1。因此p表示当前连续记录段的记录数,也是下一条连续记录与起点应有的差值。

else:
    if p==1:
        t[j-1]=res+res//10+1
    else:
        t[j-1]=res+1
    res=t[j]*10
    p=1

不满足连续条件时,结束当前记录段并将其压缩为两位数:十位是起点,个位是实际跑到的终点。若只有一条记录s,res=s×10,写入res+res//10+1即s×10+s+1,表示s至s+1;若已有连续记录,res个位已是最后一条记录,加1即可补回未记录的终点。然后以当前t[j]开始新的一段,p重新置1。

if p==1:
    t[j-1]=res+res//10+1
else:
    t[j-1]=res+1
return t

循环结束后,最后一段尚未遇到“不连续”的下一条记录,故再按同一规则完成末段压缩,返回修改后的列表。

对t=[3,4,4,5,1],依次检查如下。表中的j、p均为本轮判断时的值:

j p 判断 本轮处理后的t 加框语句累计次数
1 1 4−3=1,成立 [3,4,5,1] 1
1 2 4−3=1≠2 [35,4,5,1] 1
2 1 5−4=1,成立 [35,4,1] 2
2 2 1−4=−3≠2 [35,46,1] 2

第一轮删除的是第一个4;第二个4与起点3的差仍为1,不满足此时p=2的要求,因此另起一段。循环结束后,末尾记录1被压缩成12,返回[35,46,12]。加框处只在两次连续条件成立时执行,共2次。

第(3)小题

参考答案
  1. a[p]%10<a[p+1]%10

  2. p+=1

  3. rsu=sortv(stu[i])

程序分析

n=len(stu)
for i in range(n):
    stu[i]=orga(stu[i])
    ③
    ans=""
    for j in range(len(rsu)-1):
        ans+=str(rsu[j]%10)+'-'+str(rsu[j+1]//10)+','
    if ans=="":
        print(i+1,'号学生完成跑步任务')
    else:
        print(i+1,'号学生未完成路段:',ans[:-1])

主程序逐个处理学生。orga将该生记录转为区段编码,例如[35,46,12]表示3—5、4—6、1—2。后续遍历rsu,把前一区段的终点与后一区段的起点组成未完成路段,因此③需要得到按起点排列、已合并相交或相接区段的结果,而不能直接沿用尚未整理的编码列表。

def sortv(a):
    p=0; i=0
    while i<len(a) and p<len(a)-1:
        j=len(a)-1
        while j>i:
            ...
        if a[p]%10>=a[p+1]//10:
            ...
        elif i!=0:
            ②
        i+=1
    return a

进入sortv后,i、p均从0开始。外层每轮先进行一趟排序,再检查相邻区段能否合并;i逐轮加1,p用于定位本轮比较的相邻区段。函数返回的是经原地修改的列表a。

j=len(a)-1
while j>i:
    if a[j]<a[j-1]:
        a[j],a[j-1]=a[j-1],a[j]
    j-=1

j从表尾向左扫描。右侧元素较小时交换相邻元素,使较小的编码不断向左移动,一趟后当前后缀中的最小值到达下标i。这是从右向左进行的冒泡过程。

区段编码的十位为起点、个位为终点,编码升序首先对应起点升序;起点相同时,终点较小的排在前面。

if a[p]%10>=a[p+1]//10:
    if ①:
        a[p]=a[p]//10*10+a[p+1]%10
    a.pop(p+1)
elif i!=0:
    ②

a[p]%10取前一区段的终点,a[p+1]//10取后一区段的起点。前者不小于后者时,两段相交或首尾相接,可以合并。

①成立后,已知赋值保留前一区段的起点,把终点改为后一区段的终点;随后无论①是否成立,都会删除后一区段。是否需要改写终点,必须由两段终点的大小关系决定。若两段分离,则在i!=0时执行②。

填空分析

①

合并后的终点应为两段终点的较大值。只有后一区段终点更大时,才需要执行已有的终点改写语句,故填:

a[p]%10<a[p+1]%10

例如35和46合并时,5<6,前一编码更新为36;若是36和45,后一段完全包含在前一段中,应保持36,仅删除45。两种情况合并后均保持p不变,以便继续检查后续区段。

②

两段分离时,当前区段不能与后一段合并,需要向后移动比较位置,填:

p+=1

原程序保留i!=0这一限制,是因为第0趟排序只保证最小编码到达表首,第二个位置未必已是剩余最小值。此时若发现两段分离,不宜立即跳过表首区段,应在下一趟排序后再检查。

③

orga返回的是压缩后的区段列表,③需要调用sortv完成排序与合并,并把返回值交给后续使用的rsu,填:

rsu=sortv(stu[i])

例如2号学生的编码[35,46,12]整理为[12,36],主程序由前段终点2与后段起点3生成未完成路段2—3。

原主程序的限制:它只检查相邻已完成区段之间的空缺,未检查第一段是否从1开始、最后一段是否到6。例如记录[2,3]压缩并合并后为[24],内部循环不执行,ans为空,程序会误报完成任务,实际仍缺1—2和4—6。这一问题不能由题设三个空的预期填法解决;本题给出的6名学生均覆盖路线首尾,因此不影响这组数据的判定。