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

单选题1:
  下列二进制数中最大的是( )。  A、110     B、1010     C、1100     D、1001

答案:C

单选题2

  以下方法中,不是对文件读操作的是( )。  A、readline()     B、readlines()     C、 readtext()     D、read()

答案:C

单选题3

  以下选项,对 random.uniform(a,b)语句表述正确的是( )。 

A、随机生成一个 a 到 b 之间的整数 

B、随机生成一个 a 到 b 之间的浮点数 

C、随机生成一个 a 和 b 之外的整数 

D、随机生成一个 a 和 b

答案:B  random.uniform和random.randint的定义域都是闭区间,random.uniform会自动取小值下限,而random.randint不会,因此random.randint应该先输入下限再输入上限。其它的函数或方法的定义域都是半开区间,含头不含尾。

单选题4:  下列表达式在遍历字典 d 时,变量 x 代表字典值的是( )。  A、for x in d:         B、for x in d.keys():   C、for x in d.items():      D、for x in d.values():

答案:D     AB是键,C是键和值(项目)。

单选题5:  以下对 turtle 库中函数描述正确的是( )。  A、goto() 函数设置当前画笔移动到原点位置   B、 pensize()函数设置画笔的移动速度   C、setup()函数定义窗体的大小和相对位置   D、hideturtle()函数是将海龟显示出

答案:C

编程题1:  编程实现:  编写程序,统计 1 到 N 之间(包含 N)所有正整数中个位数为零的有几个。   例如:N=21,1 到 21 之间所有正整数中个位数为零的数有 2 个,分别为:10,20。   输入描述:输入一个正整数 N   输出描述:输出 1 到 N 之间(包含 N)所有正整数中个位数为零的有几个   样例输入:21   样例输出:2代码:

· 

· 

N=int(input())print(N//10)

编程题2

  编程实现:   小蓝和小青在玩积木搭建游戏,小蓝报一个数字 N,代表高楼的高度,小青则需要使用最少的积木搭建出高度大于 N 的高楼。  给出小蓝所报出的数字 N,及每一块正方体积木的高度,请你帮助小青找出最少需要多少块积木可以搭建出高度大于 N 的高楼。  例如:N=12,正方体积木的高度分别为 4,7,8,4。则最少需要 2 块积木,可以使搭建的高楼高度大于 12,2 块积木为 7 和 8。  输入描述:  第一行输入一个正整数 N,表示小蓝报出的数字   第二行输入多个正整数,表示已有积木块每一块的高度,正整数之间以一个英文逗号隔开(要求所有正整数之和大于 N)。  输出描述:  输出最少需要使用多少块积木,可以搭建出高度大于 N 的高楼   样例输入:  12   4,7,8,4   样例输出:  2代码:

· 

· 

· 

· 

· 

· 

· 

· 

N=int(input())lst=[int(x) for x in input().split(',')]lst.sort(reverse=True)for i in range(len(lst)):    N-=lst[i]    if N<0:        print(i+1)        break

解说:从大到小取积木就行。

编程题3:  编程实现:   输入多个由小写字母组成的英文单词,然后按字典顺序排序输出。  注:单词首字母相同时就比较第二个字母,以此类推。   输入描述:输入多个由小写字母组成的英文单词,单词之间以一个英文逗号隔开   输出描述:按字典顺序排序输出,且单词之间以一个英文逗号隔开   样例输入:python,hello,world   样例输出:hello,python,world代码:

· 

· 

· 

lst=input().split(',')lst.sort()print(",".join(lst))

解说: 字符串的list.sort()是按字典顺序排序的。

编程题4:

  编程实现: 

  小马需要将 N 件物品从河的一岸搬运到河的另一岸,每次搬运的物品为 1 到 3 件。请问小马将 N 件物品 全部搬运过去有多少种不同的方案。  例如:N=3,将 3 件物品全部搬运过去有 4 种不同的方案:   方案一:第一次搬运 1 件,第二次搬运 1 件,第三次搬运 1 件;   方案二:第一次搬运 1 件,第二次搬运 2 件;   方案三:第一次搬运 2 件,第二次搬运 1 件;   方案四:一次搬运 3 件。   输入描述:输入一个正整数 N,表示需要搬运的物品数   输出描述:输出将 N 件物品从河的一岸搬运到河的另一岸有多少种不同的方案   样例输入:3   样例输出:4代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N=int(input())count=0def move(n):    if n==0:        global count        count+=1        return    if n>0:        move(n-1)        move(n-2)        move(n-3)
move(N)print(count)

解说:  如果这是一道数学题,求方案的表达式,几乎是没办法的,这就是所谓的计算机数学了。在数学中解决问题的方法一般要先把具体问题抽象为模型。这个思想在计算机数学中同样适用。我们把样例画成如下的样子:

 

  这就是传说中的“树”,红色的点就是节点,开始节点就是树的根,最后的节点就是树的叶。方案数就是叶子的数量。问题转化为从根节点出发到叶子的路线数(路线数与叶子数相等)。从根节点出发统计节点数,就是树的遍历。

  树的遍历主要有两种方法,第一是递归法,第二是分层遍历。上面的代码采用了递归法。用递归法有两个要求:  第一、数量少时可计算(本题,数量1,2,3时都可以计算的)  第二、问题可拆解为低数量表达式:

· 

· 

· 

· 

    if n>0:        move(n-1)        move(n-2)        move(n-3)

  分层遍历就是从根节点开始,走完一层再走下一层,这过程中需要列表保留节点数据,直到最深叶子为止(最顶的叶子),代码如下:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N=int(input())count=0lst1 = [N] #开始层lst2 = []  #下层收集器while len(lst1) > 0:    for i in lst1:        for j in range(1,4):            d = i - j            if d == 0:  #到达一片叶子                count += 1                break            lst2.append(d)    lst1 = lst2  #下推一层    lst2 = []    #清空收集器
print(count)

编程题5:  编程实现:   N 个正整数,现对 N(3≤N)个正整数进行不同方式的排列,每次排列后都会按照以下规则进行一次计算,聪明的小蓝发现,排列方式不同,最后计算出的结果也不相同。   计算规则:   第一次:第一个数乘以第二个数乘以第三个数,结果记录为 M(1);  第二次:第二个数乘以第三个数乘以第四个数,结果记录为 M(2);  第三次:第三个数乘以第四个数乘以第五个数,结果记录为 M(3);  …    N-2 次:第 N-2 个数乘以第 N-1 个数乘以第 N 个数,结果记录为 M(N-2)。   最后计算 M(1)+M(2)+M(3)......M(N-2)的数值。   请找出一种排列方式使这个数值最大。

  例如:N=44 个正整数分别为 1234,那么排列方式就会有 24 种: 

  其中排列方式为 1,3,4,2 时,按照规则计算 2 次:1*3*4=12,3*4*2=24;乘积相加:12+24=36 这种排序方式是所有乘积相加的数值最大,为 36  输入描述:输入 N 个正整数(3≤N),正整数之间以一个英文逗号隔开   输出描述:输出按照规则计算后的最大数值   样例输入:1,2,3,4  样例输出:36代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

lst=[int(x) for x in input().split(",")]lst.sort(reverse=True)rst1=lst[::2]rst2=lst[1::2]rst=list(reversed(rst1))+rst2sm=0for i in range(len(rst)-2):    sm+=rst[i]*rst[i+1]*rst[i+2]
print(sm)

解说:  首先我们考虑最大值放在哪?由于开始元素和结尾元素都在乘积中出现1次,第二元素和倒数第二元素只出现2次,所以除非没有更多的位置,最大值是不应该放在这些位置上。  不难想象,最大值应该放中间;然后第二大和第三大分别在它的左右;第四大在第二大左边,第五大在第三大的右边,……如此类推,得到的数列的积之和一定最大。

  本题倒序排列后隔一个分开两个列表,一个倒过来后接上另一个列表实现这种排列。

编程题6:  编程实现:   有一块农田被划分为 N*M 块,农作物和杂草分布生长在农田中,其中农作物使用大写字母“R”表示, 杂草使用大写字母“X”表示。请计算出农田中有几块独立的农作物区域(独立的农作物区域指该区域上下左右都被杂草围住,且 N*M 以外的区域都是杂草)。   例如:N=4,M=4,4*4 的农田中农作物和杂草分布如下图:    这块农田中有 3 块独立的农作物区域(红色的 3 部分)。   输入描述:   第一行输入两个整数 N 和 M(1≤N≤100,1≤M≤100),N 表示农田的行数,M 表示农田的列数,且两个正整数之间一个英文逗号隔开   接下来的 N 行每行包括 M 个字符(字符只能为 R 或 X),R 表示农作物,X 表示杂草,字符之间一个英文逗号隔开   输出描述:   输出一个整数,表示 N*M 的农田中有几块独立的农作物区域 

  样例输入: 

  4,4 

  R,R,R,X   R,X,R,X   X,X,X,R   R,X,X,X   样例输出:  3代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N,M = map(int, input().split(","))lst = [input().split(",") for i in range(N)]def count(i, j):    if i<0 or i>N-1 or j<0 or j>M-1:        return    if lst[i][j]=="R":        lst[i][j]="X"        global cnt        cnt+=1        count(i-1,j)        count(i+1,j)        count(i,j-1)        count(i,j+1)sm=0for i in range(N):    for j in range(M):        cnt=0        count(i,j)        if cnt>0:            sm+=1
print(sm)

解说:  每一块就是一棵树,那多棵树就是深林。这里统计的深林的树的数量,同样可以用递归法解决。
  用一个循环遍历深林:

· 

· 

· 

· 

· 

· 

· 

sm=0for i in range(N):    for j in range(M):        cnt=0        count(i,j)        if cnt>0:            sm+=1

  用一个函数统计每棵树的节点数,递归:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

def count(i, j):    if i<0 or i>N-1 or j<0 or j>M-1:        return    if lst[i][j]=="R":        lst[i][j]="X"        global cnt        cnt+=1        count(i-1,j)        count(i+1,j)        count(i,j-1)        count(i,j+1)

  同样,可以用分层遍历的方法:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

N,M = map(int, input().split(","))lst = [input().split(",") for i in range(N)]rst = [] #已统计过的对象def count(i, j):    lst1 = [(i, j)]    lst2 = []    cnt=0    while len(lst1) > 0:        for kp in lst1:            if rst.count(kp) > 0: #已检查过                continue            rst.append(kp)            k, p = kp            if lst[k][p]=="R":                cnt+=1                if k - 1 > -1:                    lst2.append((k-1,p))                if k + 1 < N:                    lst2.append((k+1,p))                if p -1 > -1:                    lst2.append((k, p-1))                if p + 1 < M:                    lst2.append((k,p+1))        lst1 = lst2        lst2 = []    return cntsm=0for i in range(N):    for j in range(M):        cnt =  count(i,j)        if cnt>0:            sm+=1
print(sm)

注:深林中的节点是不共用的,所有统计过的节点就加入rst列表,然后每次检查,先检查节点是否已经统计,如果已经就跳过。

· 

· 

· 

· 

        for kp in lst1:            if rst.count(kp) > 0: #已检查过                continue            rst.append(kp)