蓝桥杯2022Python组

目录

蓝桥杯2022Python组

1.排列字母

在这里插入图片描述

用一个sorted就好了,没啥好说的

s = 'WHERETHEREISAWILLTHEREISAWAY'
s = sorted(s) # 变成列表形式了
print(''.join(s))

2.寻找整数

在这里插入图片描述

这题我刚开始以为答案只能是11和17的倍数,就在他们的倍数里面找,发现不对,他还有可能是50以上的质数的倍数。但是他肯定是11和17的倍数是没跑的,就是187的倍数,肯定不可能是187的偶数倍,因为mod2余1,所以我们从187开始搜,跨度为187*2,但是那样也很多,我们给他加一点条件看看能不能找到什么规律。

我是加了最多五个,作为条件,找到了规律他们是一个等差数列,因此我们就可以拿那个等差数列去寻找我们最终想要的

# a = 0
# res = []
# for i in range(187,10**17,374): # 不能被我除尽,一定不是187的偶数倍
#     if i % 49 == 46 and i % 48 == 41 and i % 47 == 5 and i % 46 == 15 and i % 45 == 29:
#         a = a+1
#         res.append(i)
#         if a == 5:break
# print(res)


mod = [(2, 1), (3, 2), (4, 1), (5, 4), (6, 5), (7, 4), (8, 1), (9, 2), (10, 9),
       (11, 0), (12, 5), (13, 10), (14, 11), (15, 14), (16, 9), (17, 0), (18, 11), (19, 18),
       (20, 9), (21, 11), (22, 11), (23, 15), (24, 17), (25, 9), (26, 23), (27, 20), (28, 25), (29, 16),
       (30, 29), (31, 27), (32, 25), (33, 11), (34, 17), (35, 4), (36, 29), (37, 22), (38, 37), (39, 23),
       (40, 9), (41, 1), (42, 11), (43, 11), (44, 33), (45, 29), (46, 15), (47, 5), (48, 41),(49,46)
       ]
for i in range(5458460249,10**17,12590206409 - 5458460249):
    for a,b in mod:
        if i % a != b:break
    else:print(i)

3.纸张尺寸

在这里插入图片描述

这题又变得简单了,一题难一题简单的,简单的枚举一下就好了

a = 1189 
b = 841
res = []
for i in range(10):
    res.append([a,b])
    if a > b: a = a//2
    else: b = b // 2
n = input()
if n == 'A0': 
    print(res[0][0])
    print(res[0][1])
if n == 'A1': 
    print(res[1][1])
    print(res[1][0])
if n == 'A2': 
    print(res[2][0])
    print(res[2][1])
if n == 'A3': 
    print(res[3][1])
    print(res[3][0])
if n == 'A4': 
    print(res[4][0])
    print(res[4][1])
if n == 'A5': 
    print(res[5][1])
    print(res[5][0])
if n == 'A6': 
    print(res[6][0])
    print(res[6][1])
if n == 'A7': 
    print(res[7][1])
    print(res[7][0])
if n == 'A8': 
    print(res[8][0])
    print(res[8][1])
if n == 'A9': 
    print(res[9][1])
    print(res[9][0])

4.位数排序

在这里插入图片描述

最开始的想法就是创建一个字典,每个数都对应这他自己的位数和,然后让位数和去排序,是可行的

n,m = int(input()),int(input())

dic = {}
for i in range(1,n+1):
    dic.update({i:sum([int(x) for x in str(i)])})
res = sorted(dic.items(),key = lambda x:x[1])
print(res[m-1][0])

PS 因为他本身已经因为自己的数排序了,就是1,2,3,4所以位数和排完后不需要再去对他们自己进行排个序

5.蜂巢

在这里插入图片描述

能把坐标系画出来也不难了这题,很简单,你想想,比如往东偏北60°走两格,是不是y+2,x+1?那我们就这样想,往东偏北60*走一格是y+1,x+0.5 ,这样类似的就行了。然后我们坐标系就建好了。

建好之后找他们两的位置就不难,我们可以画图发现,如果abs(y1-y2) > abs(x1-x2),那我们的最短距离就是abs(y1-y2).可以画个图尝试一下,需要的话我可以再补。

如果abs(y1-y2) < abs(x1-x2)呢,我们还是先走y轴的部分,走完呢y轴斜着走肯定x也会变,走到一个点和另一个点平行,然后再走X轴直线就好了(当然画图会形象,有条件的可以去画画)

def find(x,y,n,step):
    if n == 0:
        x -= step
        return x,y
    if n == 1:
        x -= 0.5*step
        y += step
        return x,y
    if n == 2:
        x += 0.5*step
        y += step
        return x,y
    if n == 3:
        x += step
        return x,y
    if n == 4:
        x += 0.5*step
        y -= step
        return x,y
    if n == 5:
        x -= 0.5*step
        y -= step
        return x,y

if __name__ == '__main__':
    d1,p1,q1,d2,p2,q2 = map(int,input().split())
    xb1,yb1 = find(0,0,d1,p1)
    xb,yb = find(xb1,yb1,(d1+2)%6,q1)
    xc1,yc1 = find(0,0,d2,p2)
    xc,yc = find(xc1,yc1,(d2+2)%6,q2)

    if abs(yc - yb) >= abs(xc - xb): print(abs(yc-yb))
    else: print(int(abs(yc - yb) + (abs(xc - xb) - 0.5*abs(yc - yb))))

6.消除游戏

在这里插入图片描述

很简单,我们遍历一遍,把边缘字符的坐标给加入到一个集合里,然后删除就好了。

def eliminate(s): 
    a = set()
    for i in range(1,len(s)-1):
        if s[i-1] == s[i] and s[i] != s[i + 1]:
            a.add(i+1)
            a.add(i)
        if s[i] == s[i + 1] and s[i] != s[i - 1]:
            a.add(i)
            a.add(i-1)
    s = list(s)
    for i in a:
        s[i] = ''  # 边缘的都变成’‘
    return ''.join(s)
    
if __name__ == '__main__':
    s = input()
    for _ in range(2**64):
        temp = s
        s = eliminate(s)
        if temp == s:
            print(s) 
            break
        if len(s) == 0:
            print('EMPTY')
            break

7.全排列的价值

在这里插入图片描述

这个如果写多重循环肯定会TLE的哦,我们可以发现一个递推公式

参考与https://blog.csdn.net/BlacKingZ/article/details/124066488

当然大佬最后有一块递推的部分直接略过了,我这边补充一下,就是一层一层往下推就好了,记住P1 = 0 P2 = 1

在这里插入图片描述

8.技能升级

在这里插入图片描述

我感觉他这个题简单一会难一会的,这题也蛮简单的。。我还在想有没有什么坑呢,应该是没有,就直接遍历每次取最大就好了

if __name__ == '__main__':
    n,m = map(int,input().split())
    A = []
    B = []
    for i in range(n):
        a,b = map(int,input().split())
        A.append(a)
        B.append(b)
    res = 0
    for _ in range(m):  # O(mn)
        maxa = max(A)
        res += maxa
        index1 = A.index(maxa)
        A[index1] -= B[index1]
    print(res)

PS : 也可以不用max和index ,用sorted 直接排序,但要知道sorted 在python 中的时间复杂度是O(nlogn),max和index都是O(n) ,所以我这样总复杂度是O(mn),你用sorted的话时间复杂度是O(mnlogn),会多个logn

9.最长不下降子序列

在这里插入图片描述

这题我一直没有一个很好的解法,最开始超级暴力就是一个个变,变完后去搜他这个序列的最长不下降子序列,发现时间复杂度达到了O(n^3logn),先给你们看看暴力的,应该最多只能多前30%

import copy

时间复杂度O(n^3logn) 太大了,能过1000就不错了

def isfdj(lst):
    return lst == sorted(lst)

if __name__ == '__main__':
    n,k = map(int,input().split())
    ls = [int(x) for x in input().split()]
    l = []
    for i in range(0,n-k):  #O(n)
        if i == 0:
            tmp = copy.deepcopy(ls)
            for j in range(k):     #O(k)
                tmp[j] = 0
        else:
            tmp = copy.deepcopy(ls)
            t = ls[i-1]
            for j in range(i,i+k):
                tmp[j] = t
        ll = 0
        low = 0
        high = 0
        while high < n:     #O(n)
            if isfdj(ls[low,high]): # O(nlogn)
                ll += 1
            else:
                l.append(ll)
                ll = 0
                low = high
            high += 1
        l.append(ll)
    print(len(l))

就是每个地方都根据k变,然后遍历变完之后的序列。不对。。。这个是最长连续不下降序列。。我搞错了,那我们直接看另一种吧,时间复杂度被我降到了O(O^2logn)虽然还是很大,但我能力就到这了

import copy

时间复杂度O(n^3logn) 太大了,能过1000就不错了

def isfdj(lst):
    return lst == sorted(lst)
def erfen(a,k):  # 找到单调递增序列a中 第一个比k大的元素
    l = 0
    r = n
    while l < r:
        mid = (l+r)//2
        if a[mid] > k:r = mid
        else : l = mid
        if r - l == 1:return r
    return 0

if __name__ == '__main__':
    n,k = map(int,input().split())
    ls = [int(x) for x in input().split()]
    l = []
    for i in range(0,n-k):  #O(n)
        if i == 0:
            tmp = copy.deepcopy(ls)
            for j in range(k):     #O(k)
                tmp[j] = 0
        else:
            tmp = copy.deepcopy(ls)
            t = ls[i-1]
            for j in range(i,i+k):
                tmp[j] = t

        res = []
        d =[0]*(n+1)
        d[1] = tmp[0]
        len = 1
        for i in range(1,n):
            if tmp[i] >= d[len]:
                len += 1
                d[len] = tmp[i]
            else: #换掉该换的
                j = erfen(d,tmp[i])
                d[j] = tmp[i]
        res.append(len)
    print(max(res))

最开始每个地方都根据K去变,就是把后面K个数变成最前面的一个数的前一个数的值,然后去找这个字符串的最长不下降子序列,用到了二分查找。

把最长不下降子序列放到一个d里面,d[len]表示这个子序列最大的一个数,如果后一个数大于d[len],那么len++,d[len] = 后一个数

如果后一个数小于d[len]呢?那我们就把他放到他该放的位置上去,并不是直接扔掉,他后面可能会有用的,可以代替d[len]使得最长不下降子序列的最大元素更小。那么我们现在就是要找到一个他的位置,是什么位置呢?在d中找到一个数,这个数是最先>他的,也就是在这个数之前的数都小于等于他,那么他把这个大于他的数给替换到,可以用到二分查找。总复杂度是O(nlogn)

10.最优清零方案

在这里插入图片描述

这题在我看来还是蛮简单的,我也不知道会不会TLE啊,我在蓝桥杯官网找不到这题没办法去测试。就是能消除连续K个肯定是消除连续K个对吧,那我们就从头开始遍历,把K个数当做一个滑动窗口,如果这个滑动窗口中有0,我们就往下滑一格(可以优化直接滑到什么位置,我这里没有做),没有0,我们就把这K个数全部减1,然后直到到最后。 剩下的只能一个个减去1了,就求个sum

if __name__ == '__main__':
    n,k = map(int,input().split())
    A = [int(x) for x in input().split()]

    res = 0
    for i in range(0, n - k+1):
        while 0 not in A[i:i+k]:
            for j in range(i,i+k):
                A[j] -= 1
            res += 1
    res += sum(A)
    print(res)

欢迎大家一起讨论,感觉我还是蛮多不会的

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年3月5日 下午1:41
下一篇 2023年3月5日

相关推荐