2020年蓝桥杯|省赛|python组|题目解析+代码

目录

一、门牌制作

二、跑步锻炼

三、蛇形填数

四、排序

五、寻找2020

六、成绩统计

七、单词分析

八、数字三角形

九、平面切分

一、门牌制作

【题目描述】

小蓝要为一条街的住户制作门牌号。
这条街一共有2020 位住户,门牌号从1 到2020 编号。
小蓝制作门牌的方法是先制作0 到9 这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌1017 需要依次粘贴字符1、0、1、7,即需要1 个字符0,2 个字符1,1 个字符7。
请问要制作所有的1 到2020 号门牌,总共需要多少个字符2?

【输出格式】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只输出这个整数,输出多余的内容将无法得分。

【题目解析】

由于数据量比较小,直接暴力枚举即可,计算所有2的个数

【代码实现】

print(sum([str(i).count('2') for i in range(1,2021)]))

【运行结果】

624

二、跑步锻炼

【题目描述】

小蓝每天都锻炼身体。正常情况下,小蓝每天跑1 千米。如果某天是周一或者月初(1 日),为了激励自己,小蓝要跑2 千米。如果同时是周一或月初,小蓝也是跑2 千米。小蓝跑步已经坚持了很长时间,从2000 年1 月1 日周六(含)到2020 年10 月1 日周四(含)。请问这段时间小蓝总共跑步多少千米?

这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【题目解析】

本题有三种解法:

法一:

借助datetime库直接获取日期,逐个遍历。

法二:

根据日期的规则,闰年二月29天,平年二月28天,起始的那天是周六,通过for循环遍历每一天,若为一号或者周一就跑2km,其他日期跑1km,知道2020年10月1日结束,并输出结果。

法三:

运用excel,直接生成时间序列,统计总的天数,然后筛选出周一的天数,以及一号的天数和一号并且是周一的天数。

总的跑步数=总的天数+一号的天数+周一的天数-一号并且是周一的天数

【代码实现】

方法一:

import datetime
start = datetime.date(2000, 1, 1)   #开始日期
end = datetime.date(2020, 10, 1)    #结束日期
days = datetime.timedelta(days=1)  #每次增加一天 
run = 0   #跑xx千米

while(start <= end):
    if(start.day == 1 or start.isoweekday()==1):     #一号或者周一
        run = run + 2
    else:
        run = run + 1
    start = start + days
print(run)

方法二:

month1=[0,31,29,31,30,31,30,31,31,30,31,30,31]  #闰年各月天数
month2=[0,31,28,31,30,31,30,31,31,30,31,30,31]  #平年各月天数
run=0   #跑步数
mon=5   #周几
for year in range(2000,2021):
    #判断是闰年还是平年
    if ((year%4==0)and (year%100!=0))or(year%400==0):
        month=month1
    else:
        month=month2
    for m in range(1,13):   #1月到12月
        for d in range(1,month[m]+1):   #1号到month[m]号
            if (mon==0)or (d==1):       #月初或周一跑2km
                run=run+2
            else:
                run=run+1
            mon=(mon+1)%7    #取余使其不断循环
            if (year==2020)and(m==10)and(d==1):      #2020年10月1日结束
                print(run)
                break

【运行结果】

8879

三、蛇形填数

【题目描述】

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。如下图所示,小明用从 11 开始的正整数“蛇形”填充无限大的矩阵

1 2 6 7 15 ...
3 5 8 14 ...
4 9 13 ...
10 12 ...
11 ...
...

容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列的数是多少?

【题目解析】

首先观察数字的走向与坐标的关系

(0,0)向右走

(0,1)向左下走

(1,0)向下走

(2,1)向右上走

(1,1)向右上走

(0,2)向右走

   .............

可以很容易发现,坐标相加为奇数时,向下或者左下走;偶数时向上或者向右上走。

从图可以看出向上或者向下是因为走到了上边界或者左边界。

因此根据以上判断条件,不断的按规则走,当走到20行20列(坐标是从(0,0)开始的,所以是(19,19)时退出循环)时退出循环即可。

【代码实现】

i,j,k = 0,0,0    
while True:     
    k = k+1
    if i == 19 and j == 19:   #第20行20列时,输出答案并退出循环 
        print( k)
        break 
    if (i + j)%2== 1:   #坐标相加为奇数时
        i=i+1        #向下 
        if j > 0:    #不是第一列时
            j =j- 1     #向左
    else:   #偶数时
        j =j+ 1     #向右 
        if i > 0:    #不是第一行时
            i =i- 1     #向上

【运行结果】

761

四、排序

【题目描述】

小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻. 在冒泡排序中,每次只能交换相邻的两个元素。 小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符, 则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。 例如, 对于字符串lan排序,只需要1次交换。对于字符串qiao排序, 总共需要4次交换。 小蓝找到了很多字符串试图排序,他恰巧碰到一个字符串,需要100次交换,

可是他忘了把这个字符串记下来,现在找不到了。 请帮助小蓝找一个只包含小写英文字母且没有字母重复出现的字符串,对该串的字符排序,正好需要100次交换。如果可能找到多个,请告诉小蓝最短的那个。如果最短的仍然有多个,请告诉小蓝字典序最小的那个。

【题目解析】

本题考查了冒泡排序法,冒泡排序法进行排序时,最坏的情况下需要进行n*(n-1)/2次交换,交换100,计算得出n=14.65,因为n只能取整数。当n=14时,最坏情况下91次;当n=15时,最坏情况下105次。所以该字符串的长度为15。

题目中对字符串的要求是没有重复的字母,且全为小写,还要字典序数最小的。

因此,很快可以得出,15个字母为abcdefghijklmno,最坏的情况的排序是onmlkjihgfedcba,

题目要求100次交换次序,所以手动交换5次,把字符串变为jonmlkihgfedcba(为了保证字典序数最小,直接将j提到最前面)。

下面用代码验证一下该字符串用冒泡排序法需要多少次。

【代码实现】

str1=list("jonmlkihgfedcba")  #分割字母
count=0    #交换次数初始化
#冒泡排序法
for i in range(len(str1)-1):
    for j in range(len(str1)-i-1):
        if str1[j] > str1[j+1]:    # 前面大于后面,交换次序
            k=str1[j]
            str1[j]=str1[j+1]
            str1[j+1]=k
            count=count+1
print(count)
print(str1)

【运行结果】

100
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o']

五、寻找2020

【题目描述】

小蓝有一个数字矩阵,里面只包含数字0 和2。小蓝很喜欢2020,他想找到这个数字矩阵中有多少个2020 。
小蓝只关注三种构成2020 的方式:

  • 同一行里面连续四个字符从左到右构成2020。
  • 同一列里面连续四个字符从上到下构成2020。
  • 在一条从左上到右下的斜线上连续四个字符,从左上到右下构成2020。

例如,对于下面的矩阵:

220000
000000
002202
000000
000022
002020

一共有5 个2020。其中1 个是在同一行里的,1 个是在同一列里的,3 个是斜线上的。 小蓝的矩阵比上面的矩阵要大,由于太大了,他只好将这个矩阵放在了一个文件里面。
在本试题中有一个文件2020.txt,里面给出了小蓝的矩阵。
请帮助小蓝确定在他的矩阵中有多少个2020。
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【题目解析】

第一步,需要将1.txt文件里的矩阵取出

第二步,分三种情况判断2020

  • 从左到右
  • 从上到下
  • 从左上到右下

注意:

  • 从1.txt中取出的矩阵的元素是字符类型
  • 矩阵的边界限定,需留出三个位置

【代码实现】

txt = open("1.txt", "r")      # 利用open()打开文件,并赋值给file
TOTO = txt.read().split('\n')    # 利用 .split换行分割字符串
m = len(TOTO)    # 读取矩阵的行数
n = len(TOTO[0])  # 读取矩阵的列数
count=0   #个数
#从左到右找
for i in range(m):
    for j in range(n-3):
        if (TOTO[i][j]=="2")and(TOTO[i][j+1]=="0")and(TOTO[i][j+2]=="2")and(TOTO[i][j+3]=="0"):
            count=count+1

#从上到下找  
for j in range(n):
    for i in range(m-3):
        if (TOTO[i][j]=="2")and(TOTO[i+1][j]=="0")and(TOTO[i+2][j]=="2")and(TOTO[i+3][j]=="0"):
            count=count+1
            
#从左上到右下
for i in range(n-3):
    for j in range(m-3):
        if (TOTO[i][j]=="2")and(TOTO[i+1][j+1]=="0")and(TOTO[i+2][j+2]=="2")and(TOTO[i+3][j+3]=="0"):
            count=count+1

print(count) 

【运行结果】

16520

六、成绩统计

【题目描述】

小蓝给学生们组织了一场考试,卷面总分为100 分,每个学生的得分都是一个0 到100 的整数。
如果得分至少是60 分,则称为及格。如果得分至少为85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。

【输出格式】

输入的第一行包含一个整数n,表示考试人数。
接下来n 行,每行包含一个0 至100 的整数,表示一个学生的得分。

【题目解析】

设置一个阈值,然后根据阈值将输入的分数分为不及格、及格、优秀,运用round()函数对结果四舍五入。

注意:

  • 及格人数包括及格的和优秀的
  • 输出的为整数,且是百分数

【代码实现】

n=int(input())
mun1=0  #及格数
mun2=0  #优秀数
for i in range(n):
    nn=int(input())
    if nn>=60:
        mun1=mun1+1
        if nn>=85:
            mun2=mun2+1
mun1=str(round((mun1/n)*100))+"%"
mun2=str(round((mun2/n)*100))+"%"
print(mun1)
print(mun2)

七、单词分析

【题目描述】

小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。

现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这个字母出现的次数。

【输入描述】

输入一行包含一个单词,单词只由小写英文字母组成。

对于所有的评测用例,输入的单词长度不超过 1000。

【输出描述】

输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪 个。如果有多个字母出现的次数相等,输出字典序最小的那个。

第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数。

【题目解析】

运用for循环,使用.count()函数计算字符串中各个字母出现的次数,将出现次数最多且相同的字母取出,放到一个空数组中,再对数组中的元素进行排序,取第一个元素就是字典序最小的。

【代码实现】

word=input()       #接受字符串
max=0      #字母出现的最多的次数
b=[]       #装出现次数最多且相同的字母
for i in word:     
    mun=word.count(i)   #计数字母出现的次数
    if mun>max:
        max=mun
for j in word:
    if word.count(j)==max:    #出现次数最多的所有字母
        b.append(j)
b.sort()   #排序
print(b[0])
print(max)

八、数字三角形

【题目描述】

888837c1866f11daf9b40c636a520d86.png

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。

路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。

【输入描述】

输入的第一行包含一个整数 N (1≤N≤100),表示三角形的行数。

下面的 NN 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。

【输出描述】

输出一个整数,表示答案。

【题目解析】

通过题目的规则,遍历数组

  • 左边界的数,只能来源于右上方
  • 右边界的数,只能来源于左下方
  • 其他的数,来源于max(左上方,右上方)

最后,由于向左下走的次数与向右下走的次数相差不能超过 1,所以答案为底层中间的那个数,偶数层时取中间两个数中那个大的。

【代码实现】

row = int(input())  # 输入数据
s = [list(map(int, input().split())) for i in range(row)]
# 循环遍历计算
for i in range(1, row):      #第一行只有一个元素,所以直接从第二行开始
    for j in range(i+1):    #i行有i个元素
        if j == 0:  # 最左边元素只能由右上方得到
            s[i][j] = s[i][j] + s[i - 1][j]
        elif j == i:  # 最右边元素只能由左上方得到
            s[i][j] = s[i][j] + s[i - 1][j - 1]
        else:  # 其余元素由上方较大值得到
            s[i][j] = s[i][j] + max(s[i - 1][j],s[i - 1][j-1])
if row%2 == 1:  # 如果是奇数行,则返回最中间值
    print(s[row-1][row // 2])
else:  # 偶数行则返回中间较大值
    print(max(s[row-1][row // 2 - 1], s[row-1][row // 2]))

九、平面切分

【题目描述】

平面上有N条直线,其中第i ii条直线是y=Ai​×x+Bi​,请计算这些直线将平面分成了几个部分。

【输入描述】

第一行包含一个整数N。

以下N行,每行包含两个整数A i , B i 
其中,1 ≤ N ≤ 1000 , −10^5 ≤ Ai​,Bi​ ≤ 10^5。

【输出描述】

输出一个整数,表示答案。

【题目解析】

一条线时,平面被分为2个

两条线时

  • 重合:2个
  • 平行:3个
  • 相交:4个

三条线时

  • 重合:2、3
  • 平行:4
  • 相交:一二个交点:6;三个交点:7

.............

可以看出,每增加一条直线,若增加m个交点,则增加m+1个平面。。。。

【代码实现】

N=int(input())
ls=[tuple(map(int,input().split(" "))) for i in range(N)]    #获取A,B
se=set(ls)     #转化成集合,去重
ls=list(se)    #转回列表

if len(ls)==1:
    re=2
else:
    re=2
    #计算新增的直线与原有直线的交点数
    for i in range(1,len(ls)):
        a1,b1=ls[i]
        se=set()  #初始化空集合
        for j in range(i):
            a2,b2=ls[j]
            if a1!=a2:
                x=(b1-b2)/(a1-a2)
                y=a1*x+b1
                se.add((x,y))   
        re=re+len(se)+1
print(re)

  • 12
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷烬亿下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值