2021年软件类第十二届蓝桥杯第二场省赛 python组 A-E题解

Posted 风信子的猫Redamancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021年软件类第十二届蓝桥杯第二场省赛 python组 A-E题解相关的知识,希望对你有一定的参考价值。

2021年软件类第十二届蓝桥杯第二场省赛 python组 A-E题解

文章目录

试题 A:求余

思路

这道题,emmmm,没思路,直接算,可能测试一下吧

代码

print(2021%20)

答案

1

试题 B:双阶乘

思路

这道题也很简单,我们求最后五位,就是%100000,然后双阶乘,实际上就是每隔1个相乘,所以我们直接循环计算即可

代码

dp = [1]*2022

for i in range(3,2022,2):
    dp[i] = dp[i-2]*i
print(dp[2021]%100000) # 答案59375

答案

59375

题目 C:格点

思路

这道题我们的思路是很清晰的,首先我们的坐标一定是整数,这样我们的数就是格点,其次我们在第一象限获取符合条件的数

在我们的条件中,题目说,要坐标x和坐标y相乘小于等于2021,我们就可以遍历这之间的数,如果我们的数的坐标相乘小于等于2021,那我们的计数就+1,最后打印出我们最后的值即可

代码

ans = 0
for x in range(1,2021+1): # 保证起码是1~2021的数据
    for y in range(1,2021//x + 1): # 范围是1 ~ 2021//x
        if x*y <= 2021: # 如果x*y<=2021
            ans += 1
print(ans) # 答案:15698

答案

15698

试题 D:整数分解

思路

首先最简单的思路就是5重循环,不过O(n^5)的复杂度,让人望而却步,我也尝试进行一个改进一下范围,但是结果还是不近如意,除非在考试的时候,顶多运行5个小时一定出的来,或者利用C++运行应该会快很多的

好咯,废话不多说,这里讲一下正解,其实呢,这道题可以用隔板的思想

比如说3分为两个数,实际上就是3个小球,一个隔板,有几种放法,3 = 1 + 2,@|@@或者是3 = 2 + 1,@@|@,所以这就是一个组合的问题了,我们可以看到,3个小球有2个空隙(最前面和最后面不算),放一个隔板,就是 C 2 1 C_2^1 C21

所以这样来看,我们的2021分为五个数,就是2021个球放4个隔板,有几种放法,根据上面来看,一共2020个空隙,4个隔板,一共就是 C 2020 4 C_2020^4 C20204

代码

# cnt = 0
# for a in range(1,2022):
#     for b in range(1,2022-a-3):
#         for c in range(1,2022-a-b-2):
#             for d in range(1,2022-a-b-c-1):
#                 for e in range(1,2022-a-b-c-d):
#                     if a + b + c + d + e == 2021:
#                         cnt += 1
# print(cnt)

import math # 利用math库的组合数
print(math.comb(2020,4)) # 答案:694422703815
print(2020*2019*2018*2017*2016//5//4//3//2//1)

答案

694422703815

试题 E:城邦

思路

这道题实际上也很简单,其实就是一道最小生成数的模板题,那我们可以直接套最小生成树的模板

理清思路了以后,我们可以理清楚一下这道题的思路,首先,我们有2021个城邦,我们要使所有城邦可以互通,最大是 C 2021 2 C_2021^2 C20212种方案,相当于每两个城邦建一座桥,不过这种耗费是很大的,并且,我们的题目说了,我们会建立2020座桥,并且要求花费是最小的,所以这就是在考最小生成树的知识点

生成树定义:对于有n个顶点的连通图,只有n-1条边的连通子图就是它的生成树。(既然是树就不可能存在环)

所以简言之,生成树就是以最少的边(n-1)条边来连接所有顶点的图。但是:

生成树不唯一(取的边的组合不唯一),当我们赋予了边的权值时,所有边的权值的和也就必然有一个最小值。即最小生成树

知道定义了以后,我们这里用的是克鲁斯卡算法,kruskal的基本算法思想,创建边的数组(i,j,weihgt),按照边的权值排序(贪心),然后,初始化各个顶点作为一个独立的集合(并查集思想),遍历边(贪心),如果i和j不在同一集合,意味着i,j不连通(并查集),对应的边应当取过来,权值和累加一次,否则如果i和j在同一集合(已经连通),意味着这条边不应取过来…直至取完n-1条边,只剩下一个集合,这个集合包含所有点(连通性)那么最终的权值和一定是最小的(最小权值和)。

代码

# 初始化祖先
father = [i for i in range(2022)]

def get_father(x):
    # 压缩路径,查找集合
    if x != father[x]:
        father[x] = get_father(father[x])
    return father[x]

# 合并两节点        
def union(x,y):
    xfather,yfather = get_father(x),get_father(y)
    if xfather != yfather:
        father[xfather] = yfather

# 计算权重
def get_weight(x,y):
    s = 0
    while x or y:
        if x%10 != y%10:
            s += x%10 + y%10
        x //= 10
        y //= 10
    return s

#创建边集(i,j,weight)
edge=[]
for i in range(1,2022):
    for j in range(1,2022):
        edge.append((i,j,get_weight(i,j)))
edge.sort(key=lambda x:x[2]) # 根据权重排序

cnt = 0
ans = 0
for i in edge:
    # 不在同一个连通分量中,并且没有建立2020座桥
    if get_father(i[0]) != get_father(i[1]) and cnt < 2020:
        union(i[0],i[1])
        cnt += 1
        ans += i[2]
print(ans) # 答案:4046

答案

4046

以上是关于2021年软件类第十二届蓝桥杯第二场省赛 python组 A-E题解的主要内容,如果未能解决你的问题,请参考以下文章

2021年软件类第十二届蓝桥杯 省赛 python组 A-E题解

2021年软件类第十二届蓝桥杯 省赛 python组 F-J题解

2021 第十二届蓝桥杯大赛软件赛省赛(第二场),C/C++大学B组题解

2021 第十二届蓝桥杯大赛软件赛省赛(第二场),C/C++大学B组题解

2021.5.9 第十二届蓝桥杯大赛软件赛省赛第二场大学B组(个人题解)

《蓝桥杯真题》:2021单片机省赛第二场(第十二届第二场)暨第十三届蓝桥杯赛前模拟试题