草庐IT

【蓝桥真题】——2021年蓝桥python组省赛真题+解析+代码(通俗易懂版)

小蓝刷题 2023-04-04 原文

 大家好,我是爱刷题的小蓝,欢迎交流指正~ 

全网最详细蓝桥杯真题+解析+代码,绝对通俗易懂,一点就通!

专治各种没资源,没思路,没代码等新手入门级BUG


🏆全文目录

试题A:卡片

1 真题​

2 解析

3 代码

试题B:直线

1 真题​

2 解析

3 代码

试题C:货物摆放

1 真题

2 解析

3 代码

试题D:路径⭐⭐

1 真题​

2 解析

3 代码

试题E:回路计数⭐⭐

1 真题

 2 解析

3 代码

试题F:时间显示⭐⭐

1 真题

2 解析

3 代码

试题G:杨辉三角形⭐⭐⭐

1 真题

2 解析

3 代码

试题H:左孩子右兄弟⭐⭐

1 真题​

2 解析

3 代码

试题I:异或数列⭐⭐⭐

1 真题

2 解析

3 代码

试题 J: 括号序列⭐⭐⭐

1 真题

2 解析

3 代码


试题A:卡片

1 真题


2 解析

难度系数:

考察题型:枚举 

涉及知识点: 字符串:str()  计数方法:.count()

思路分析:

第一题就这么暴力,不愧是BF杯。循环就完事了!

经过一波分析,从材料中“拼11时卡片1已经只有一张了”推理出卡片1最先用光。

原因是:0~9这十张卡片是从1开始拼的,1最先被使用,也就意味着1最先用光。

小蓝得出思路:先循环遍历可以拼出的数字,再将整数格式转换成字符串格式,

接上count()方法统计"1"出现的次数那么当"1"出现了2021次时,就搞定啦~


3 代码

#卡片
cnt=0                        #计数器:统计1的个数
i=1                          #从1开始遍历   
while True:                  #循环次数未知,用while循环
    cnt+=str(i).count("1")   #.count("1")方法:统计i中"1"出现的次数
    if cnt>2021:             #如果"1"出现超过2021次,说明是卡片1用完了的下一次,找到了关键i
        print(i-1)           #输出结果3181
        break
    i+=1

试题B:直线

1 真题


2 解析

难度系数:

考察题型:枚举  数论

涉及知识点: 集合docker=set()  斜率截距公式(k,b)

思路分析:

一条普普通通的直线,竟然能变出这么多花样?直线,接招!( •̀ ω •́ )✧

首先创建二维列表存放坐标系,然后二重循环遍历,给每个坐标点赋初值。

因为要统计不同的直线,所以用直线的性质:斜率截距 来区分,并存放到集合容器里,

最后一点小细节,当斜率不存在时,k会报错,

所以单独计算,最后直接加上20条垂直x轴的直线。


3 代码

#直线
M=[[x,y] for x in range(20) for y in range(21)] #创建二维列表:代表xy坐标系
d=set()                            #创建集合属性的容器:因为集合里的元素不会重复
for i in M:                        #二重循环遍历每个坐标
    x1,y1=i[0],i[1]                #注意书写格式:a,b=c,d
    for j in M:
      x2,y2=j[0],j[1]
      if x1==x2:                   #特殊情况:直线垂直时斜率不存在,先跳过最后计算
          continue
      k=(y2-y1)/(x2-x1)            #斜率公式
      b=(x2*y1-x1*y2)/(x2-x1)      #截距公式
      if (k,b) not in d:           #存入容器里没有的(斜率,截距)对
          d.add((k,b))
print(len(d)+20)                   #输出结果:容器的长度40237+斜率不存在的20种情况=40257

试题C:货物摆放

1 真题


2 解析

难度系数:⭐⭐

考察题型:枚举 数论

涉及知识点: 约数 集合

思路分析:

长宽高,三重循环,枚举暴力,yyds!(´▽`ʃ♡ƪ)

两个知识点:一个是约数,另一个是集合。

1、判断约数算法: n%i==0

约数指的是被整除后没有余数的数。

举个栗子:3%1==0  3%3==0  1和3就是3的约数。

2、创建集合容器方法:docker=set()

选用集合作为容器存放数据,是因为集合的数据不会重复。相同的数据不会重复添加。


3 代码

n=2021041820210418               #货物数量
cnt=0                            #count统计值赋初始值0
d=set()                          #容器docker赋予集合属性
for i in range(1,int(n**0.5)+1): #循环遍历,筛选n的约数(对n开根号可加快速度)
    if n%i==0:                   #如果可被整除,判断为约数
        d.add(i)                 #添加约数
        d.add(n//i)
for i in d:                      #三重循环遍历容器docker里的约数
    for j in d:                  
        for k in d:
            if i*j*k==n:         #满足条件
                cnt+=1           #方案数+1
print(cnt)                       #print(2430)

试题D:路径

1 真题


2 解析

难度系数:⭐⭐

考察题型:数论  动态规划 

涉及知识点:最小公倍数 最短路径 

思路分析:

这道题可谓是究极嵌套!融合了最短路径,最小公倍数和动态规划。一个不会就全凉了~

最小公倍数我已经整理成精简模板放代码里了,考试时直接套模板就行。

动态规划经典的做题步骤有5步。

 第一步:明白dp[i]的含义

 dp[i] #i:结点编号1~2021   #dp[i]:当前结点到结点1的最短路径长度
 dp[j] #j:结点编号i+1~i+21 #dp[j]:当前结点到结点i的最短路径长度

第二步:给dp数组初始化赋值

dp=[float('inf')]*(n+1)         #创建列表赋值为无穷大
dp[1]=0                         #结点1的长度初始化为0

第三步:弄清dp[i]遍历的顺序

for i in range(1,n+1):          #先遍历结点a:遍历结点1~n
    for j in range(i+1,i+22):   #再遍历结点b:遍历结点i+1~i+21

第四步:搞懂递推公式min()

别看递推公式短短一行,其中包含的信息量巨大!这是最为关键的一步。

(记得先回头去看第一步dp[i],dp[j]的定义,对理解下面的解析很有帮助)

此时dp[j]就在比较两个路径的长度,它只选择最短的那条路走:

第一条路:dp[j],代表之前存在dp列表里的最小路径(当前结点到结点1的最小路径)。

第二条路:dp[i]+lcm(i,j),代表假如现在的dp[i]加上新路lcm(i,j),这时候的路径长度。

比较dp[j]dp[i]+lcm(i,j)哪条路更短,只走近路(min)的dp[j]就跟它走(╹ڡ╹ )

dp[j]=min(dp[j],dp[i]+lcm(i,j))  #递推公式

第五步:打印数组dp[n]

print(dp[n])                    #输出结果:10266837

 参考资料:

python的动态规划我是看这个视频学的,学会里面的经典案例,动态规划一通百通~

清华计算机博士带你学习Python算法+数据结构_哔哩哔哩_bilibili


3 代码

#最小公倍数模板(least common multiple)
def lcm(a,b):
    s=a*b
    while b:
        a,b=b,a%b
    return s//a

#最短路径(dp)
n=2021                          #结点数量
dp=[float('inf')]*(n+1)         #创建列表赋值为无穷大
dp[1]=0                         #结点1的长度初始化为0
for i in range(1,n+1):          #结点a:遍历结点1~n
    for j in range(i+1,i+22):   #结点b:遍历结点i+1~i+21
        if j>n:                 #j超出结点范围时
            break               #结束循环
        dp[j]=min(dp[j],dp[i]+lcm(i,j))#递推公式
print(dp[n])                    #输出结果:10266837


试题E:回路计数

1 真题


 2 解析

难度系数:⭐⭐⭐

考察题型:动态规划 数论

涉及知识点:状态压缩DP 互质

思路分析:

from math import gcd
n = 21
m = 1 << n
dp = [[0 for j in range(n)] for i in range(m)]        #dp[i][j]对于状态i,i的二进制表示中为1的位置 表示走过了教学楼j
load = [[False for j in range(n)] for i in range(n)]  #存储i, j之间是否有路
for i in range(1, n + 1):
    for j in range(1, n + 1):
        if gcd(i, j) == 1:
            load[i - 1][j - 1] = True
dp[1][0] = 1
for i in range(1, m):           #枚举每一种状态
    for j in range(n):
        if i >> j & 1:          #判断状态i是否包含第j栋教学楼
            for k in range(n):  #枚举所有可能从教学楼k走到教学楼j的情况
                if i - (1 << j) >> k & 1 and load[k][j]:  #判断状态i除去j后是否包含k
                    dp[i][j] += dp[i - (1 << j)][k]
print(sum(dp[m - 1]) - dp[m - 1][0])    #输出结果:881012367360

试题F:时间显示

1 真题


2 解析

难度系数:⭐⭐

考察题型:时间

涉及知识点:时间模块

思路分析:

主要用到两个时间函数,简单到可以3行搞定(^∀^●)ノシ

当然前提是你得知道几个关键的时间函数。

先转换成时间对象格式,再转换成可读字符串格式。

time.gmtime()        #转换为time.struct_time类型的时间对象的秒数

time.asctime()        #返回一个可读形式的字符串 Tue Feb 17 09:42:58 2009


3 代码

#内置模块方法
import time
n=int(input())
print(time.asctime(time.gmtime(n//1000))[11:19])

#底层算法方法
n = 1618708103123 #1618708103123ms
n //= 1000        #ms->s:1618708103s
n %= 24*60*60     #最近1天:4103s
s = n % 60        #23s
n //= 60          #s->min:68min
h = n // 60       #1h
m = n %  60       #8min
print("{:02d}:{:02d}:{:02d}".format(h,m,s)) #01:08:23

试题G:杨辉三角形

1 真题


2 解析

难度系数:⭐⭐⭐⭐

考察题型:枚举 查找 数论

涉及知识点: 模拟 二分查找 组合数

思路分析:

组合数公式

具体思路参考:

第十二届蓝桥杯B组C/C++省赛—H题(杨辉三角)_思维题_萌小帝的博客-CSDN博客


3 代码

# 试题 G: 杨辉三角形
# 组合值模板
def C(a, b):  
    res = 1
    fz = a #分子
    for fm in range(1,b+1): #1~b
        res = res * fz // fm#递推公式=分子//分母
        fz -= 1
        if res > n:
            return res
    return res
#二分查找
def check(k): #k:斜行
    l, r = 2*k, n   #赋初值left:2k right:n
    while l < r:
        mid = l + r >> 1 # >>1:相当于(l+r)//2
        if C(mid, k) >= n:
            r = mid
        else:
            l = mid + 1
            
    if C(r, k) != n:
        return False
    print(r * (r + 1) // 2 + k + 1)#查找位置
    return True

n = int(input())
if n == 1:
    print(1)
else:
    for k in range(16,0,-1):#从16斜行枚举
        if check(k)==True:
            break

试题H:左孩子右兄弟

1 真题


2 解析

难度系数:⭐⭐⭐⭐

考察题型:数据结构 动态规划

涉及知识点:二叉树 树型DP

思路分析:

没有思路肿么办?先暴力破解试试看吧!时间超了也有15分能拿。

先根据题目思路,定义一个树节点类,再初始化结点。

定义一个递归函数,求树的最大高度,最后遍历即可。

一步步转化,求二叉树最高高度->孩子结点个数


3 代码

#树形结构版
#定义结点类
class node():
    def __init__(self,val):
        self.val=val        #父结点值
        self.child=[]       #结点孩子
tree=[None,node(val=0)]     #初始化树
#初始化树列表
n=int(input())
for i in range(2,n+1):     
    m=int(input())
    tree.append(node(val=m))
    tree[m].child.append(i)
#最大长度-递归函数
def maxlen(n:node):
    if len(n.child)==0:    #无孩子,高度为0
        return 0
    else:
        return len(n.child)+max(maxlen(tree[temp]) for temp in n.child)
print(maxlen(tree[1]))      #从根节点开始遍历
#二维列表法
a = [[]for i in range(100001)]  #测试数据最大为十万
n = int(input())                #测试数量:5
for i in range(2, n + 1):       #结点编号:2,3,4,5
    fu = int(input())           #输入父节点:1,1,1,2
    a[fu].append(i)             #测试结果:[[], [2, 3, 4], [5], [],[]]
#树型DP
def dfs(t):
    ans = 0
    for i in range(len(a[t])):  #t:1 len:3 i:0,1,2
        ans = max(ans, dfs(a[t][i])+len(a[t]))
    return ans
print(dfs(1))

试题I:异或数列

1 真题

 

 


2 解析

难度系数:⭐⭐⭐⭐

考察题型:数论 搜索

涉及知识点:位运算 dfs 

思路分析:

持续更新中······

参考思路:

蓝桥杯2021年第十二届省赛-异或数列_zy98zy998的博客-CSDN博客_蓝桥杯异或数列


3 代码

#持续更新中······

试题 J: 括号序列

1 真题


2 解析

难度系数:⭐⭐⭐⭐

考察题型:枚举

涉及知识点:模块

思路分析:

持续更新中·······

参考思路:

【蓝桥杯真题】2021年蓝桥杯省赛A组题目解析+代码(python组)_薛崇祥的博客-CSDN博客_2021蓝桥杯省赛python


3 代码

#括号序列
MOD = (int)(1e9 + 7)

def add(x, y):  
    return (x + y) % MOD

def brackets():
    f = [[0 for i in range(n + 10)] for i in range(n + 10)]  
    f[0][0] = 1

    for i in range(1, n + 1):
        if str[i] == '(':
            for j in range(1, n + 1):
                f[i][j] = f[i - 1][j - 1]
        else:
            f[i][0] = add(f[i - 1][0], f[i - 1][1])
            for j in range(1, n + 1):
                f[i][j] = add(f[i - 1][j + 1], f[i][j - 1])

    for i in range(n + 1):
        if f[n][i]:
            return f[n][i]

str = list(input())
n = len(str)

str.insert(0, 0)  #使目标字符串下标从1开始
ans_l = brackets()

str.reverse()
for i in range(n):
    if str[i] == '(':
        str[i] = ')'
    else:
        str[i] = '('
str.insert(0, 0)  #使目标字符串下标从 1 开始
ans_r = brackets()

print(ans_l * ans_r % MOD)


旅途的最后,小蓝祝愿旅行者们好运连连🌟~

有关【蓝桥真题】——2021年蓝桥python组省赛真题+解析+代码(通俗易懂版)的更多相关文章

  1. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  6. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  7. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  8. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  9. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  10. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

随机推荐