当前位置:   article > 正文

【蓝桥杯真题】提升篇 详解 Python_python递归蓝桥杯

python递归蓝桥杯

 距离蓝桥杯25天

欢迎来到Python蓝桥杯提升篇

难度依次提升 做好心理准备噢


1.巧排扑克牌

问题分析:手算 作图模拟 编号0-12 ,0作为"最底层的牌"" ,即下面规定越靠近左侧越下面

第一轮 可以确定6个数字,因为都是隔着一项出牌,在对应编号上写上对应数字

由于12以后看似没有牌了,我们需要重新组合,在第一轮过程中,未被编号的将后移,注意顺序

 结果:

print('7, A, Q, 2, 8, 3, J, 4, 9, 5, K, 6, 10')

2.质数拆分 

问题分析:先用埃筛法 把0—2019的质数选出来 存入数组Prime 

然后利用背包的思想对于第j个质数,只有取和不取的两种可能

dp[i][j]:代表从j个质数中选 恰好和为i的方案数

那么dp[i][j]=prime[j]不取的方案数+prime[j]取的方案数,i为背包容量(总数和)

如果prime[j]>i,那么prime[j]取的方案数=0

如果prime[j]<i ,那么prime[j]可取,prime[j]取的方案数!=0,因而其的计算方法为:在i的容量大小下预留prime[j]的空间 前j-1个质数可构成的方案

最后初始化dp[0]全部设为1

结果:55965365465060

  1. max=2019
  2. is_prime=[1]*2020#is_prime[i]代表i是否为素数,是为1,不是为0
  3. prime=[0]#埃筛 特殊将0作为第0个质数
  4. for i in range(2,max+1):
  5. if is_prime[i]:
  6. prime.append(i)
  7. j=i+i
  8. while j<=max:
  9. is_prime[j]=0
  10. j+=i
  11. #dp[i][j]代表从j个质数中选 恰好和为i的方案数
  12. #dp[i][j]=prime[j]不取的方案数+prime[j]取的方案数
  13. #若prime[j]<=i:dp[i][j]=dp[i-prime[j]][j-1]+dp[i][j-1]
  14. #如果prime[j]>i dp[i][j]=dp[i][j-1]
  15. n=len(prime)
  16. dp=[[0]*(n) for i in range(0,2020)]
  17. dp[0]=[1]*(n)
  18. for i in range(1,2020):
  19. for j in range(1,n):
  20. if prime[j]>i:
  21. dp[i][j]=dp[i][j-1]
  22. else:
  23. dp[i][j]=dp[i-prime[j]][j-1]+dp[i][j-1]
  24. print(dp[2019][-1])

3.日志统计

 问题分析:签到题,需要用到‘’字典‘’,以Id为Key,r[id]=[t1,t2,t3...],将点赞时刻填入列表。

将列表升序排列,遍历列表,以点赞数目K为间距,如果时间差<=d,符合,id可选。

代码已经AC

  1. n,d,k=map(int,input().split())
  2. r=dict()
  3. for i in range(n):
  4. ts,id=map(int,input().split())
  5. if id not in r.keys():
  6. r[id]=[ts]
  7. else:
  8. r[id].append(ts)
  9. s=[]#记录符合的id
  10. for i in r.keys():
  11. l=r[i]
  12. l.sort()
  13. if len(l)<k:
  14. continue
  15. for j in range(len(l)):
  16. if j+k-1<=len(l)-1:
  17. if l[j+k-1]-l[j]<=d-1:
  18. s.append(i)
  19. break
  20. s.sort()
  21. for i in s:
  22. print(i)

4. 递增三元组

 

 问题分析:遍历数组b,当访问到b[i],统计a中<b[i]的个数p,统计c中>b[i]的个数q

cnt:作为答案输出;统计完后,cnt+=p*q

那么该如何统计?

最简单的方法:先将a,c排序 遍历a(c),统计个数即可 但这样只能过75分

  1. n=int(input())
  2. a=list(map(int,input().split()))
  3. b=list(map(int,input().split()))
  4. c=list(map(int,input().split()))
  5. a.sort()
  6. c.sort(reverse=True)
  7. cnt=0
  8. for i in range(n):
  9. j,k=0,0
  10. t=b[i]
  11. while j<=n-1 and a[j]<t:j+=1
  12. while k<=n-1 and c[k]>t:k+=1
  13. cnt+=j*k
  14. print(j,k)
  15. print(cnt)#超时 75分

如何优化:利用前缀和,用空间换时间,每次统计的时候直接从列表查询

对于数组a而言,创建一个列表ans,ans[i]代表i在数组a中出现的次数

对于数组c而言,创建一个列表cns,cns[i]代表i在数组c中出现的次数

创建一个数组x,作为ans的前缀和,x[i]代表数组a中<=i的数字出现的次数

创建一个数组y,作为cns的前缀和,y[i]代表数组c中<=i的数字出现的次数

对于一个一个确定的b[i] 我们统计a中<b[i]的个数,即查询p=x[b[i]-1]

对于一个一个确定的b[i] 我们统计c中>b[i]的个数,即查询q=y[-1]-y[b[i]]

细节的地方:对于x[b[i]-1],b[i]-1有可能越界,即b[i]-1>len(x)-1

那么q=x[-1],这是由于a中最大的元素可能比b[i]-1还要小,所以此时前缀和x的最大下标小于b[i]-1,那么a中小于b[i]的个数一定也就是x[-1]个

同时,b[i]-1有可能变为负数,,即b[i]<1,即b[i]=0,但那对应的x[b[i]-1]并不是我们想要的。实际上,这种特殊情况,p=0,因为a中不会有比0更小的数字了。

对于y[-1]-y[b[i]],y[b[i]]有可能越界,如果len(y)-1<=b[i],那么意味着c中最大的元素小于b[i],那么q=0,因为c中不会有比b[i]更大的数字了。

  1. n=int(input())
  2. a=list(map(int,input().split()))
  3. b=list(map(int,input().split()))
  4. c=list(map(int,input().split()))
  5. ans=[0 for i in range(max(a)+1)]
  6. for i in a:
  7. ans[i]+=1
  8. x=[0 for i in range(max(a)+1)]
  9. x[0]=a.count(0)
  10. for j in range(1,max(a)+1):
  11. x[j]=x[j-1]+ans[j]
  12. cns=[0 for i in range(max(c)+1)]
  13. for i in c:
  14. cns[i]+=1
  15. y=[0 for i in range(max(c)+1)]
  16. y[0]=c.count(0)
  17. for j in range(1,max(c)+1):
  18. y[j]=y[j-1]+cns[j]
  19. cnt=0
  20. for k in range(n):
  21. if b[k]-1>len(x)-1:
  22. p=x[-1]
  23. elif b[k]-1<0:
  24. p=0
  25. else:
  26. p=x[b[k]-1]
  27. if len(y)-1<=b[k]:
  28. q=0
  29. else:
  30. q=y[-1]-y[b[k]]
  31. cnt+=p*q
  32. print(cnt)

5. 发现环

问题分析利用拓扑排序来检测环 可以看我之前这篇文章

!!如果对拓扑排序没有理解的,下面讲的会很难理解,需要基于对拓扑排序的理解基础!

与有向图应用的拓扑排序不同:我们需要做几点改变

第一个就是入度的概念:之前的入度指的是其他点指向u点的边数

这里由于是无向图 只要其他点连着u点,不论方向,边数都应该累加进来

第二个就是:原有删除结点是基于该结点的入度为0,这里需要稍作改变,改作入度为1

其他的保持不变,最后输出[1,2....,N]和拓扑序列seq的差集再排序一下就好了

  1. #构图
  2. n=int(input())
  3. G=dict((i,[]) for i in range(1,n+1))
  4. for i in range(n):
  5. x,y=map(int,input().split())
  6. G[x].append(y)
  7. G[y].append(x)
  8. indegrees=dict((i,0) for i in G.keys())
  9. for i in G.keys():
  10. for j in G[i]:
  11. indegrees[j]+=1
  12. stack=[i for i in indegrees.keys() if indegrees[i]==1]
  13. seq=[]#拓扑序列
  14. while stack:
  15. tmp=stack.pop()
  16. seq.append(tmp)
  17. for i in G[tmp]:
  18. indegrees[i]-=1
  19. if indegrees[i]==1:
  20. stack.append(i)
  21. ans=list(set([i for i in range(1,n+1)])-set(seq))
  22. ans.sort()
  23. for i in range(len(ans)-1):
  24. print(ans[i],end=' ')
  25. print(ans[-1])

有任何疑惑欢迎提问!程序题还是要自己多尝试多实践! 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/64165
推荐阅读
相关标签
  

闽ICP备14008679号