16届蓝桥杯Python赛道B组的一点点比赛经验

早上好啊,大伙。蓝桥杯软件赛不是以及结束了嘛,然后前面我们写了两套题目,这一期来总结一下这一期的蓝桥,然后也来和大家交流一下题目

本期题单:攻击次数、最长字符串、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),这样一转换之后思路就会清晰很多。

然后第二点,我们可以对所有的乘积进行统计,也就是前置处理。
举个栗子 ——

乘积情况数量
11 * 11
21 * 2 / 2 * 12
31 * 3 / 3 * 11
41 * 4 / 2 * 2 / 4 * 13
51 * 5 / 5 * 12
………………

也就是说对于2 的指数幂结果的一种情况需要 - 1,然后对于其它结果都可以互换,直接 * 2就行了。

第三点,这里就开始计算 <= L 的所有情况,对于每一个值,都是两个数相乘,而这里的值来源于我们的第二步,下面给大伙举个栗子 ——

情况数量
10
21 * 1 + 1 * 11
31 * 2 + 1 * 1 / 2 * 1 + 1* 1 / 1 * 1 + 2 * 1 / 1 * 1 + 1 * 24
41 * 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 * 28
………………

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)

感谢大伙观看,别忘了三连支持一下

大家也可以关注一下我的其它专栏,同样精彩喔~

下期见咯~

请添加图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黑不拉几的小白兔

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

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

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

打赏作者

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

抵扣说明:

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

余额充值