距离比赛很快了,希望和我一起准备的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 个数。
输出描述
输出一行一个整数代表所求的和。
题目分析:
这道题需要花功夫好好讲解一下,因为小郑也研究了蛮久,上一次没做出来...
在这里特别感激我的一个好兄弟
蓝桥 倍数问题 枚举优化_愿此后再无WA的博客-CSDN博客
我的思路很多从他那里学到的,所以下面的很多分析会引用他的原话(因为讲的太好了!)
首先,暴力的方法,3层for循环肯定是超时的,说明需要改变方法。
设x+y+z=nk (x,y,z,n,k>0) ,那么必然有
(x%k+y%k+z%k)%k=0(依据运算法则得到)
问题就转化为,已知原先的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<k,t=k-i-j,对于一组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)
如果对你有帮助,留下三连可以吗!
有问题欢迎评论区提问!!