蓝桥杯2020省赛Python
第一题:门牌制作
用了一个时间复杂度是n的算法,反正是填空题也不会出现TLE的事,只要别太离谱就行了。
利用python 的count函数
res = 0
for i in range(1,2021):
i = str(i)
res += i.count('2')
print(res)
答案是2
第二题:寻找2020
就一行一列的找吧,先遍历每一行,再遍历每一列,这样对于第i行,只要j+4 <= 总列数,就可以遍历矩阵的[i][j],[i][j+1]…[i][j+3],看看他是否等于2020
对于列的呢,只要当前的行数 i + 3 < 总行数 就可以更上面的一样遍历,行和列换一下而已
斜着的同样的,只要i + 3 < 总行数,j + 3 < 总列数
PS:j + 3 < 总列数 和j+4 <= 总列数是一样的,只不过第一个的时候下面要用到j+4 我就写j+4了
nums = [[2, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 0, 2],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 2, 2],
[0, 0, 2, 0, 2, 0],
]
res = 0
for i in range(len(nums)): # 行
for j in range(len(nums[0])): # 列
if j + 4 <= len(nums[0]): # 超出了
a = nums[i][j:j+4]
if a == [2,0,2,0]:
res += 1
if i+3 < len(nums):
b = nums[i][j]*1000 + nums[i+1][j] * 100 + nums[i+2][j] *10 + nums[i+3][j]
if b == 2020:
res += 1
if i+3 < len(nums) and j+3 < len(nums[0]):
c = nums[i][j] * 1000 + nums[i+1][j+1] * 100 +nums[i+2][j+2] * 10 + nums[i+3][j+3]
if c ==2020:
res += 1
print(res)
第三题:跑步锻炼
就判断呗,如果是周一或者月初,就 + 2 ,否则就加1,这里不用特殊考虑同时的情况,因为我们如果是周一的话或者月初的话都会直接continue,只会加一次2,python有专门的datetime库可以做这道题
import datetime
a = datetime.date(2000,1,1)
b = datetime.date(2020,10,2)
res = 0
while True:
if a == b: break
if a.day == 1:
res += 2
a = a + datetime.timedelta(days = 1)
continue
if a.isoweekday() == 1:
res += 2
a = a+datetime.timedelta(days = 1)
continue
res += 1
a = a + datetime.timedelta(days = 1)
print(res)
4.蛇形填数
就填呗,如果i是偶数,就j从0到i-1 顺着填,否则就反过来
lst = [[] for _ in range(40)]
lst[0].append(1)
num=1
for i in range(2,40):
if i % 2 == 0:
for j in range(i):
num += 1
lst[j].append(num)
else:
for j in range(i):
num += 1
lst[i - j -1].append(num)
for i in range(len(lst)):
print(i + 1, lst[i])
print(lst[19][19])
PS 我看了一下,直接找规律我估计也行
5.排序
这就需要了解一下冒泡排序的原理了,首先如果n个数全都倒着排的话,一共有 n-1 + n-2 + n-3 … + 1次要交换顺序
又因为他要最短的英文顺序,所以我们就先按逆序排,当有15个英文字母全都逆序的时候,总共要交换105次。又要字典序小,那就是o…a了。
接着又因为字典序小,所以我们尽量把小的往第一个放,同时满足交换100次,那就把j放到前面,这样前面五个单词就少跟j交换一次了,所以答案是
print('jonmlkihgfedcba')
第六题:成绩统计
这题就比较简单就不多说明了
if __name__ == '__main__':
n = int(input())
jige = 0
youxiu = 0
for i in range(n):
m = int(input())
if m >= 85:
youxiu += 1
jige += 1
elif m >= 60:
jige += 1
print('{:.0f}%'.format((jige/n)*100))
print('{:.0f}%'.format((youxiu/n)*100))
第七题:单词分析
最开始我感觉应该用count函数来做,但后面想想又要排字典序是有点麻烦的,我们就把他放到collections来做,里面的defaultdict(int)就可以用来计数,然后转化成字典
import collections
s = input()
dic = collections.defaultdict(int) # 参数输int就可以计数
for i in s:
dic[i] += 1
dic = dict(dic.items())
dic = sorted(dic.items(),key= lambda x:x[0], reverse=False) # 先按字典序排 升序,排完就变成一个列表了
dic = sorted(dic, key = lambda x:x[1],reverse=True) # 再按大小排,这样就都排好了 降序
print(dic[0][0])
print(dic[0][1])
第八题:数字三角形
最开始我看的时候我还以为是最基本的数字三角形,写完发现答案不对,我的是30,他是27,又看了遍题目发现他要求向左和向右次数之差不能超过1.
然后我又愚蠢的去写了一个,到达每一个顶点的向左向右的次数都不能超过1,发现还是不对,因为这样就限制了整体。他只要求到最后一行的时候,路径向左和向右的次数相差不能超过1
最后推了一遍,如果n是奇数,那么要到最后一行并且路径向左向右次数不能超过1的话,他只能到达中间那个。如果n是偶数,那么他只能到达中间两个(这个方法是过的了我去试了证明没问题)
# 如果符合要求的话 n 为奇数只有最后一行的中间点符合 偶数只有中间两个点符合
if __name__ == '__main__':
n = int(input())
f,a = [[-1]*(n+1) for _ in range(n+1)],[[0] for _ in range(N)]
for i in range(1,n+1):
a[i] += [int(x) for x in input().split()]
f[1][1] = a[1][1]
for i in range(2,n+1): # 第i行
for j in range(1,i+1): # 第j列
f[i][j] = max(f[i-1][j] + a[i][j], f[i-1][j-1] + a[i][j])
if n % 2 == 0:
res = max(f[n][n//2],f[n][n//2+1])
else:
res = f[n][n//2+1]
print(res)
第九题:平面切分
这道题因为我之前pythontip 上面刷过,所以做起来不会感觉很难,就是找规律,如果后面加进来的线和前面的线有n个不同的交点,那么他就会多加n+1个平面
n = int(input())
lines = []
for i in range(n):
a, b = map(int, input().split())
lines.append((a, b))
lines = list(set(lines)) # 去重
def cross(line1,line2): # 求交点
A1,B1,A2,B2 = line1[0],line1[1],line2[0],line2[1]
if A1 - A2 == 0: return # 返回NONE
x = (B2 - B1) / (A1 - A2)
y = A1 * x + B1
x = round(x, 10)
y = round(y, 10)
return (x, y)
ci = [1] *(n+1) # 第i条直接加入对答案的贡献,下标从0开始,默认那个1就已经加上了
node = set()
for i in range(1,n): # 从第二条线开始
node.clear()
for j in range(i):
tmp = cross(lines[i],lines[j])
if tmp == None: continue
node.add(tmp)
ci[i] += len(node)
print(sum(ci[:n])+1) # 加上最开始其实是有两个平面,我们只算了一个
第十题:装饰珠
嗯最后一道题还是很有趣的,对于这种题我一般来说是只要能做出来就好,不考虑TLE。。所以我用了一种算是暴力的做法。
其实他并不在意六件装备是怎么样的,他只在意总共的孔数和等级以及所有珠子的等级和他的价值,那么我们先把所有装备的孔数和等级存储起来,
lv[i] 表示等级为i的物品的个数
limit[i]表示等级为i的珠子最后能放多少个
value[i][j]表示等级为i的珠子放了j个的价值
lv = [0]*5 # 表示等级为i的孔的数量
limit = [0]*5
value = [[0] for i in range(5)]
for i in range(6):
a = list(map(int,input().split()))
for i in range(1,len(a)):
lv[a[i]] += 1 #等级为i的物品+1
m = int(input())
for i in range(m):
zhu = list(map(int,input().split()))
limit[zhu[0]] = zhu[1] # limit[i] 表示等级为i的珠子最多镶嵌多少个
value[zhu[0]] += zhu[2:] # value[i][j] 表示等级为i的珠子用了j个的价值
好了现在都存好了,我们就开始遍历所有的可能性,
就遍历等级为4的珠子放i个 ,为3的珠子放j个,要注意的是,等级为4的珠子最多能放min(limit[4],lv[4])个,也就是不能超过等级4的珠子的限制和等级为4的装备的孔数量,等级为3的同理,只不过他可以放在等级为4和等级为3的装备孔中。
res = 0
# 对每个珠子的等级进行枚举
for i in range(min(lv[4],limit[4])+1): # 等级为4的选i个
for j in range(min(lv[3] + lv[4] - i,limit[3])+1): # 等级为3的珠子能放进3和4的孔中
for k in range(min(lv[4] + lv[3] + lv[2] -i -j,limit[2])+1):
for l in range(min(lv[4] + lv[3] + lv[2] + lv[1] -i -j -k,limit[1])+1):
res = max(res,value[4][i] + value[3][j] + value[2][k] + value[1][l])
print(res)
完整代码如下
lv = [0]*5 # 表示等级为i的孔的数量
limit = [0]*5
value = [[0] for i in range(5)]
# print(summ)
for i in range(6):
a = list(map(int,input().split()))
for i in range(1,len(a)):
lv[a[i]] += 1 #等级为i的物品+1
m = int(input())
for i in range(m):
zhu = list(map(int,input().split()))
limit[zhu[0]] = zhu[1] # limit[i] 表示等级为i的珠子最多镶嵌多少个
value[zhu[0]] += zhu[2:] # value[i][j] 表示等级为i的珠子用了j个的价值
res = 0
# 对每个珠子的等级进行枚举
for i in range(min(lv[4],limit[4])+1): # 等级为4的选i个
for j in range(min(lv[3] + lv[4] - i,limit[3])+1): # 等级为3的珠子能放进3和4的孔中
for k in range(min(lv[4] + lv[3] + lv[2] -i -j,limit[2])+1):
for l in range(min(lv[4] + lv[3] + lv[2] + lv[1] -i -j -k,limit[1])+1):
res = max(res,value[4][i] + value[3][j] + value[2][k] + value[1][l])
print(res)