【蓝桥杯真题】16天冲刺 Python

距离比赛很快了,希望和我一起准备的PY党能更加熟练的掌握Python! 

 1.距离和(模拟赛填空题)

问题描述:

两个字母之间的距离定义为它们在字母表中位置的距离。例如 A和 C 的距离为 2,L 和 Q 的距离为 5。

对于一个字符串,我们称字符串中两两字符之间的距离之和为字符串的内部距离。

例如:ZOO 的内部距离为 22,其中 ZZ 和 OO 的距离为 11。

请问,LANQIAO 的内部距离是多少?

s=input()

ans=0
for i in range(len(s)):
    for j in range(i+1,len(s)):
        ans+=abs(ord(s[i])-ord(s[j]))
print(ans)

题目分析 :

就是考察一个Ascii码,两个字母Ascci差值的绝对值就是距离 

两层循环遍历 累加即可


2.扩散 

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝在一张无限大的特殊画布上作画。

这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。

小蓝在画布上首先点了一下几个点:(0, 0), (2020, 11), (11, 14), (2000, 2000)

只有这几个格子上有黑色,其它位置都是白色的。

每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。

请问,经过 2020 分钟后,画布上有多少个格子是黑色的。

题目分析 :

考察一个多源BFS,可以借鉴ACwing模拟赛农田灌溉那题,一样一样的,我在这篇博客写了详细的解析:【蓝桥杯真题】18天Python组冲刺 心得总结_Py小郑的博客-CSDN博客

不过这道题,PY伙伴如果用普通的列表来模拟队列,是跑不出来的,太慢了。

因为列表删除和插入的复杂度是O(n),数据量大这题。

需要借助PY自带的库里面的deque(双向队列),它的时间复杂是O(1),半分钟就能跑出来了。

通过这题最主要的还是学习了使用deque,帮助我们提高速度!

collections.deque学习传送门: Python collections模块之deque()详解_chl183的博客-CSDN博客_deque()

import collections

dx=[-1,1,0,0]
dy=[0,0,1,-1]

pre={(0,0):(0,0),(2020, 11):(2020,11),(11, 14):(11, 14),(2000, 2000):(2000, 2000)}
ans=4
queue=collections.deque()
queue.append((0,0,0))
queue.append((2020, 11, 0))
queue.append((11, 14, 0))
queue.append((2000, 2000, 0))

while queue:
    t=queue.popleft()
    if t[2]==2020:
        print(ans)
        break
    else:
        for i in range(4):
            nx,ny=t[0]+dx[i],t[1]+dy[i]
            if (nx,ny) not in pre.keys():
                pre[(nx,ny)]=(t[0],t[1])
                queue.append((nx,ny,t[2]+1))
                ans+=1
#扩散 20312088
                

3.错误票据 

可以看我这篇文章的第一题 

蓝桥杯备战练习 python冲击省一_Py小郑的博客-CSDN博客

4.倍数问题

众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 nn 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。

输入描述

第一行包括 2 个正整数 n, K。

第二行 n 个正整数,代表给定的 n 个数。

输出描述

输出一行一个整数代表所求的和。

题目分析: 

这道题需要花功夫好好讲解一下,因为小郑也研究了蛮久,上一次没做出来...

在这里特别感激我的一个好兄弟【蓝桥杯真题】16天冲刺 Python_第1张图片

 蓝桥 倍数问题 枚举优化_愿此后再无WA的博客-CSDN博客

我的思路很多从他那里学到的,所以下面的很多分析会引用他的原话(因为讲的太好了!)

首先,暴力的方法,3层for循环肯定是超时的,说明需要改变方法。

设x+y+z=nk (x,y,z,n,k>0) ,那么必然有

(x%k+y%k+z%k)%k=0(依据运算法则得到)【蓝桥杯真题】16天冲刺 Python_第2张图片

问题就转化为,已知原先的n个数构成一个集合A,然后对每个数取余构成一个新集合B,在集合B中,取3个元素使得他们的和是k的倍数,且余数对应的在集合A中的元素相加之后和最大。

我们不妨设置一个字典 dic[i]=[x,y,z...]:代表数字x,y,z..对k取余后的结果是i

由于我们总是希望取的数字较大,不妨前将集合A降序排列(从大到小),这样对所有的数取余后放到字典里,每个key对应的列表一定是从大到小的。

n,k=map(int,input().split())

a=list(map(int,input().split()))
a.sort(reverse=True)
b=dict()

for i in range(len(a)):
    r=a[i]%k
    if r not in b.keys():
        b[r]=[a[i]]
    else:
        b[r].append(a[i])

设置答案为ans,初始为0,接下来就是寻找余数组合(满足之和是k的倍数),并更新ans

如果枚举了前两个余数i,j,那么第三个余数t是唯一确定的,不需要三层循环(尽可能减少循环优化程序)

原因如下 ,设i,j,t都是集合A元素通过对k取余得到的,必然i,j,t均满足范围(0,k)

那么i+j+t必然满足范围(0,3k),那么i+j+t= k or 2k 才符合题意

而i+j满足范围(0,2k),那么当2k>i+j>k,t=2k-i-j,

当0于一组i,j,i+j的范围是确定的,所以说第三个余数t是唯一确定

for i in range(k):
    for j in range(k):
        t = k-i-j if (i+j)<= k else 2*k-i-j

然后就是更新ans了。

对于3个余数,无非三种情况,三个余数相同,两个余数相同,一个余数相同(互异)

如果三个余数相同,且这个余数对应的列表长度(元素个数)>=3,那么是可行解,否则无解,因为凑不出3个数出来

如果两个余数相同,且这个余数对应的列表长度(元素个数)>=3,且第三个余数(与这两个不同的)对应的列表长度(元素个数)>=1(也就是非空),那么是可行解,否则无解

如果一个余数相同,只要这三个互异余数对应的列表非空,存在可行解。

然后不断把ans和可行解比较,ans不断更新变大。事实上,在两个余数相同这种情况下,可以分成3种,因为可以是12,13,23。

for i in range(k):
    for j in range(k):
        t = k-i-j if (i+j)<= k else 2*k-i-j
        if i==j==t:
            if len(b[t])>=3:
                ans=max(ans,b[t][0]+b[t][1]+b[t][2])
        elif i==j:
            if len(b[i])>=2 and len(b[t])>=1:
                ans=max(ans,b[i][0]+b[i][1]+b[t][0])
        elif i==t:
            if len(b[i])>=2 and len(b[j])>=1:
                ans=max(ans,b[i][0]+b[i][1]+b[j][0])
        elif j==t:
            if len(b[j])>=2 and len(b[i])>=1:
                ans=max(ans,b[j][0]+b[j][1]+b[i][0])
        else:#三个互异
            if len(b[i])>=1 and len(b[j])>=1and len(b[t])>=1:
                ans=max(ans,b[i][0]+b[j][0]+b[t][0])

 报了key error,因为key不存在,所以当余数 not in b的时候,就可以直接下一次循环了

for i in range(k):
    for j in range(k):
        t = k-i-j if (i+j)<= k else 2*k-i-j
        if i not in b or j not in b or t not in b:
            continue
        if i==j==t:
            if len(b[t])>=3:
                ans=max(ans,b[t][0]+b[t][1]+b[t][2])
        elif i==j:
            if len(b[i])>=2:
                ans=max(ans,b[i][0]+b[i][1]+b[t][0])
        elif i==t:
            if len(b[i])>=2:
                ans=max(ans,b[i][0]+b[i][1]+b[j][0])
        elif j==t:
            if len(b[j])>=2:
                ans=max(ans,b[j][0]+b[j][1]+b[i][0])
        else:#三个互异
            ans=max(ans,b[i][0]+b[j][0]+b[t][0])

综上代码

n,k=map(int,input().split())

a=list(map(int,input().split()))
a.sort(reverse=True)
b=dict()

for i in range(len(a)):
    r=a[i]%k
    if r not in b.keys():
        b[r]=[a[i]]
    else:
        b[r].append(a[i])

ans=0

for i in range(k):
    for j in range(k):
        t = k-i-j if (i+j)<= k else 2*k-i-j
        if i not in b or j not in b or t not in b:
            continue
        if i==j==t:
            if len(b[t])>=3:
                ans=max(ans,b[t][0]+b[t][1]+b[t][2])
        elif i==j:
            if len(b[i])>=2:
                ans=max(ans,b[i][0]+b[i][1]+b[t][0])
        elif i==t:
            if len(b[i])>=2:
                ans=max(ans,b[i][0]+b[i][1]+b[j][0])
        elif j==t:
            if len(b[j])>=2:
                ans=max(ans,b[j][0]+b[j][1]+b[i][0])
        else:#三个互异
            ans=max(ans,b[i][0]+b[j][0]+b[t][0])
print(ans)

如果对你有帮助,留下三连可以吗!

有问题欢迎评论区提问!! 

你可能感兴趣的:(Python,笔记,蓝桥杯,蓝桥杯,算法,数据结构,python)