早上好啊,大伙。蓝桥杯软件赛不是以及结束了嘛,然后前面我们写了两套题目,这一期来总结一下这一期的蓝桥,然后也来和大家交流一下题目
本期题单:攻击次数、最长字符串、LQ图形、最多次数、A * B Problem、园艺、书架还原、异或求和
文章目录
前言
总得来说,在我看来没有上一届的题目那么难了,这一届题目难度没有那么大,但是对于优化的难度是很大的,没有像上一届那样不会这个算法就无从下手,什么并查集,什么动态,想想就头疼。(题目照片是从别的大佬那边偷的,勿喷),然后本篇的代码都是后期重新写的,所以不一定能向大伙还原我考试时候的真实思路。
A. 攻击次数
思路分析
这一题没什么难度,就按照题目要求来算就行了,就是考完之后和大伙交流,不知道是 103 还是 104,虽然但是吧,小白兔是写的 104,错了的话只能说便宜你们了 T_T。
代码
boss = 2025
ans = 1
while boss > 0:
boss -= 5
if ans % 2 == 0:
boss -= 2
else:
boss -= 15
if ans % 3 == 0:
boss -= 7
elif ans % 3 == 1:
boss -= 2
elif ans % 3 == 2:
boss -= 10
ans += 1
print(ans)
B. 最长字符串
思路分析
这一题其实还蛮麻烦的,我当时是用的一个偷鸡的方法,可以和大伙说的是,测试数据里的最长子串是9,然后长度为 1 的子串可以凑出26字母,然后长度为 2 的不同子串 是675,就差一个就全都有了,也就是这么个思路,大伙可以就是说写题目不用那么老实。
OK,上面是我当时偷鸡的过程,然后下面来分享一下我的解法 ——
我用一个二位列表将不同长度的字符分开存放,然后遍历该长度的所有子串,然后遍历比它小的所有字符串,如果比它小的所有字符串里有一个能够全部都在它的里面,那它就是成立的。
然后对于判断部分,我是用的一个哈希表,记录下它的所有字母,因为存在相同字母的情况,所以不能用 in 来判断,然后它可以是乱序的,所以我是采用的哈希。
然后我的结果是 6
代码
lst = [[] for _ in range(20)] # 因为最长长度是 9 ,所以不用开很大
ans = [[] for _ in range(20)] # 用来记录符合的字符串
ans[2] = lst[2]
for i in range(10): # 因为找文件位置比较麻烦,所以我是直接复制粘贴,也差不多
x = input()
lst[len(x)].append(x)
for i in range(3, 10): # 因为以及判断出来了长度为 1 和 2的是有的,所以就直接从 3 开始了
for j in lst[i]:
word = [0] * 26
for k in j:
word[ord(k)-97] += 1
for k in range(len(ans[i-1])):
temp = word.copy() # 因为有多个字符串,不能把原来记录的列表破坏掉
for l in ans[i-1][k]:
if temp[ord(l)-97] <= 0:
break
temp[ord(l)-97] -= 1
else:
ans[i].append(j)
break
print(ans)
完蛋了大伙,我回顾代码的时候,感觉我比赛的时候写错了,T_T。
C. LQ图形
思路分析
这一题比较简单了,就按照下面图片里的样子来输出就行了。
代码
w, h, v = map(int, input().split())
for i in range(h):
print('Q' * w)
for i in range(w):
print('Q' * (w + v))
D. 最多次数
思路分析
这一题,我的解法大概率过不了所有样例。
我是用集合来记录,这样就不用判断重复的问题,只需要判断是不是l q b这三个字符就行了,最后判断长度。
代码
s = input()
ans = i = 0
while i < len(s):
x = s[i: i + 3]
z = set()
for j in x:
if j == 'l' or j == 'q' or j == 'b':
z.add(j)
if len(z) == 3:
ans += 1
i += 2
i += 1
print(ans)
E. A * B Problem
思路分析
这一题是我感觉我这次里面写的最有技术含量的代码了,写了我一个小时啊,脑子都写乱了。
首先第一点,我们不应该被题目中的 (Xa,Ya)(Xb,Yb)来进行处理,应该转换成 (Xa,Xb)(Ya,Yb),这样一转换之后思路就会清晰很多。
然后第二点,我们可以对所有的乘积进行统计,也就是前置处理。
举个栗子 ——
乘积 | 情况 | 数量 |
---|---|---|
1 | 1 * 1 | 1 |
2 | 1 * 2 / 2 * 1 | 2 |
3 | 1 * 3 / 3 * 1 | 1 |
4 | 1 * 4 / 2 * 2 / 4 * 1 | 3 |
5 | 1 * 5 / 5 * 1 | 2 |
…… | …… | …… |
也就是说对于2 的指数幂结果的一种情况需要 - 1,然后对于其它结果都可以互换,直接 * 2就行了。
第三点,这里就开始计算 <= L 的所有情况,对于每一个值,都是两个数相乘,而这里的值来源于我们的第二步,下面给大伙举个栗子 ——
和 | 情况 | 数量 |
---|---|---|
1 | 无 | 0 |
2 | 1 * 1 + 1 * 1 | 1 |
3 | 1 * 2 + 1 * 1 / 2 * 1 + 1* 1 / 1 * 1 + 2 * 1 / 1 * 1 + 1 * 2 | 4 |
4 | 1 * 3 + 1 * 1 / 3 * 1 + 1 * 1 / 1 * 1 + 1 * 3 / 1 * 1 + 3 * 1 / 2 * 1 + 1 * 2 / 2 * 1 + 2 * 1 / 1 * 2 + 2 * 1 / 1 * 2 + 1 * 2 | 8 |
…… | …… | …… |
OK,大概分析到这里,但是我这个应该还是过不了所有的,甚至都不一定是对的,大伙可以一起交流一下。
代码
def Init(n):
lst = [0] * (n + 10)
for i in range(1, n + 1):
for j in range(1, int(i ** 0.5) + 1):
if i % j == 0:
if j == i // j:
lst[i] += 1 # 两个数相同就只加一次
else:
lst[i] += 2 # 两个数不同可以互换
return lst
L = int(input())
lst = Init(L)
ans = 0
for i in range(1, L + 1):
for j in range(1, i // 2 + 1):
ans += lst[j] * lst[i - j] * 2
if i % 2 == 0:
ans -= lst[i // 2] ** 2
print(ans)
F. 园艺
思路分析
这题没什么想法,就直接暴力留保底分了。
遍历从任意树开始,然后遍历任意间隔,然后用高度来判断是否成立。
代码
n = int(input())
lst = list(map(int, input().split()))
ans = 1
for i in range(n):
for j in range(i+1, n):
cnt = 1
if lst[i] >= lst[j]:
continue
d = j - i
t = j + d
cnt += 1
while t < n:
if lst[t] >= lst[j]:
cnt += 1
j = t
t = t + d
else:
break
ans = max(ans, cnt)
print(ans)
G. 书架还原
思路分析
我初步猜测是模拟sort函数,然后我模拟了快排和选择排序,对于小数据选择排序准确率会高一点,所以我就交了选择排序。
代码
n = int(input())
lst = list(map(int, input().split()))
cnt = 0
for i in range(n):
Min = min(lst[i:])
x = lst.index(Min)
if x != i:
lst[x], lst[i] = lst[i], lst[x]
cnt += 1
print(cnt)
H.异或求和
思路分析
这一题完全没有优化的思路,就写了最基本的代码,应该能过40%
直接暴力了,按照题目要求直接算
代码
n = int(input())
lst = list(map(int, input().split()))
ans = 0
for i in range(n):
for j in range(i+1, n):
ans += (lst[i] ^ lst[j]) * (j - i)
print(ans)