第十四届蓝桥杯青少组Python省赛真题解

单选题1:

 

答案:A

单选题2:

 

答案:A  注:含头不含尾的偶数。

单选题3:

答案:D  注:sorted返回集合的列表副本。

单选题4:

答案:B  

单选题5:

答案:D    注:也许没学过复数,但从题中可知复数有2部分——实部与虚部,real是“实”,不可能是虚数部分。

编程题1:
代码:

· 

· 

N = int(input())print(N+N)


编程题2:代码:

· 

· 

s = input()print(s[0]+s[-1])


编程题3:代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N = int(input())nums = list(map(int, input().split(',')))K = int(input())#构建全部集合all = set()def plus(ns,rst):    if len(rst) == K:        all.add(sum(rst))        rst.clear()    if len(ns) + len(rst) < K:            return    for i in range(len(ns)):        ns1 = ns.copy()        rst1 = rst.copy()        rst1.append(ns1.pop(i))         plus(ns1,rst1)
plus(nums,[])
#合数个数hs = 0def checkPN(pn):    for i in range(2,pn//2+1):        if pn % i == 0:            return 1    return 0for it in all:    hs += checkPN(it)    rst = [str(len(all)),str(hs)]
print(",".join(rst))

解说:  这主要是组合问题,附带质数与合数的概念编程。为了能使没学过组合数学知识的人能理解,本解法采用手动组合:集合中抽出一个元素与剩下的元素组合,如此类推。  Python列表的实现方法是:浅拷贝原列表list.copy(),然后list.pop(i)一个元素放入浅拷贝的结果列表中,用剩下的列表和这个浅拷贝的结果列表递归调用。核心代码如下:

· 

· 

· 

· 

· 

    for i in range(len(ns)):        ns1 = ns.copy()        rst1 = rst.copy()        rst1.append(ns1.pop(i))         plus(ns1,rst1)

  递归函数plus除了核心代码外,还要返回条件:当列表的元素数与已有结果数之和小于K,代码如下:

· 

· 

    if len(ns) + len(rst) < K:            return

  递归函数plus还需要统计,当所选元素达到K个时,产生一个组合,计算结果,清理结果列表,进入下一个递归过程:

· 

· 

· 

    if len(rst) == K:        all.add(sum(rst))        rst.clear()

  采用合数的概念找出合数的个数,代码如下:

· 

· 

· 

· 

· 

· 

· 

· 

· 

#合数个数hs = 0def checkPN(pn):    for i in range(2,pn//2+1):        if pn % i == 0:            return 1    return 0for it in all:    hs += checkPN(it)


编程题4:代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N = int(input())X, Y = map(int, input().split(','))#N行的杨辉三角形,用直角的杨辉三角形问题就非常明显line = [1]yh = [line]for i in range(1,N):    temp = [1]    for j in range(1,len(line)):        temp.append(line[j]+line[j-1])    temp.append(1)    yh.append(temp)    line=tempxyv = yh[X-1][Y-1]ycv = 0for i in range(Y-1,N):    ycv += yh[i][Y-1]
rst = str(xyv), str(ycv)
print(",".join(rst))

解说:  把杨辉三角形画成直角的,因此可以认为杨辉三角形是切去右上角的(对角线除外)的矩阵(当然也可以用0补全为矩阵),所谓的行列,就是这个矩阵的行列了。

 

  因此,只要生成杨辉三角形的行列表,问题就解决了。本处采用循环法逐行生成,代码如下:

· 

· 

· 

· 

· 

· 

· 

· 

· 

line = [1]yh = [line]for i in range(1,N):    temp = [1]    for j in range(1,len(line)):        temp.append(line[j]+line[j-1])    temp.append(1)    yh.append(temp)    line=temp

  X行Y列的值:

· 

xyv = yh[X-1][Y-1]

  Y列的和:

· 

· 

· 

ycv = 0for i in range(Y-1,N):    ycv += yh[i][Y-1]

 

编程题5

代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N = int(input())nums = list(map(int,input().split()))#构建01矩阵maxHigh = max(nums)mx = []for i in range(N):    mx.append([1]*nums[i]+[0]*(maxHigh-nums[i]))
minHigh = min(nums)#最大面积maxA = minHigh * N#分层统计for i in range(minHigh,maxHigh):    s = 0    j = 0    while j < N:        while j < N and mx[j][i] == 0:  #定位到非0            j += 1        while j < N and mx[j][i] > 0:  #连续块            s += 1            j += 1        if s > 0:            tmp = s * (i+1)  #矩形面积            if tmp > maxA:                maxA = tmp            s = 0            print(maxA)        

解说:  从“上面有砖,下面一定有砖“的事实出发,只要从底层开始往上逐层统计就可以得到最大的矩形。  我们用一个列表表示1列砖,为了便于分层统计,用0填充与最高列长度相同:

· 

· 

· 

· 

maxHigh = max(nums)mx = []for i in range(N):    mx.append([1]*nums[i]+[0]*(maxHigh-nums[i]))

  用循环法按层统计,循环体内含两个循环,第一个用于定位开始的1,第二个循环用于统计连续1的个数,从而计算矩形面积。

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

for i in range(minHigh,maxHigh):    s = 0    j = 0    while j < N:        while j < N and mx[j][i] == 0:  #定位到非0            j += 1        while j < N and mx[j][i] > 0:  #连续块            s += 1            j += 1        if s > 0:            tmp = s * (i+1)  #矩形面积            if tmp > maxA:                maxA = tmp            s = 0

 

编程题6

代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N = int(input())rooms = [set(input().split(',')) for i in range(N)]A, B = map(int, input().split(','))A, B = A-1, B-1
def checkLink(lst, tar):    for r in lst:        if len(r & tar) > 0: #与其中一个相连            return True    return False
rA = rooms[A]rB = rooms[B]if len(rA & rB) > 0: #A,B直通    minR = 1else:    minR = -1    sm = 0     #分层统计    lst1 = [rA]    rooms.remove(rA)    rooms.remove(rB)    lst2 = rooms    while len(lst1)>0 and len(lst2)>0:        sm += 1        hasFound = False        tmpLst1 = []        tmpLst2 = []        for r in lst2:            if checkLink(lst1,r):                if len(r & rB) > 0: #通B                    sm += 1                    hasFound = True                    break                else:                    tmpLst1.append(r) #压入下层            else:                tmpLst2.append(r)                            if hasFound:            minR = sm            break        lst1=tmpLst1        lst2=tmpLst2  #下一层
print(minR)            

解说:  每个房间都可以与0个到多个房间相连,抽象出来就是“图”。那么是无向图还是有向图呢?  我们仔细想一想,对于求从A节点(房间)到B节点的最短路径,因此图中的回环是没有意义的。于是这个问题就可以转化为“有向图”求最短路径问题。本文采用有向图的分层遍历法求解。  由于多个房间可以有同一个传送门,使用集合的交集进行判定最好不过了。例如,A直通B代码:

· 

· 

if len(rA & rB) > 0: #A,B直通    minR = 1

  有向图的分层遍历法求解:第一层是A房间,尝试A与其它房间(B除外)关联,如果有连接,检查是否与B房间相连,如果是就结束,否则加入收集器1(tmpLst1,与上一层有联系);如果无连接,加入收集2(tmpLst2,与上一层无联系)。代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

            if checkLink(lst1,r):                if len(r & rB) > 0: #通B                    sm += 1                    hasFound = True                    break                else:                    tmpLst1.append(r) #压入下层            else:                tmpLst2.append(r)

  往下推层:收集器1、2分别赋值给lst1、2,进入下一轮循环:

· 

· 

        lst1=tmpLst1        lst2=tmpLst2  #下一层

  循环条件,lst1和lst2都有元素:

· 

while len(lst1)>0 and len(lst2)>0: