第十二届蓝桥杯省赛B组 做题记录(python)
2022/1/11 17:05:29
本文主要是介绍第十二届蓝桥杯省赛B组 做题记录(python),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
蓝桥杯
- 结果填空
- 空间
- 卡片
- 直线
- 货物摆放
- 路径
- 程序设计
- 时间显示
- 砝码称重
- 杨辉三角形
- 括号序列
结果填空
空间
256*1024*1024*8/32=67108864
卡片
n=1 #卡片1所用数量 x=1 while n<2021: x+=1 n+=str(x).count("1") if n == 2021: print(x) else: print(x-1) #3181
直线
这题的话借鉴大佬的思路,用两点式直线方程:
(y1-y2) * x +(x2-x1) * y +( x1 * y2 - x2 * y1)=0
最后算出的结果是Ax+By+C=0
的格式,只要约分后的A、B、C不相同即可视为不同直线
lt=[] for i in range(20): for j in range(21): lt.append((i,j)) def gcd(x,y): if y==0: return x return gcd(y,x%y) out=set() for i in range(len(lt)-1): x1,y1=lt[i] for j in range(i+1,len(lt)): x2,y2=lt[j] A=y1-y2 B=x2-x1 C=x1*y2-x2*y1 k=gcd(gcd(A,B),C) #最大公约数 out.add((A/k,B/k,C/k)) print(len(out)) #40257
货物摆放
import math n=2021041820210418 lt=set() #集合会比列表更快 out=0 for i in range(1,int(math.sqrt(n))+1): if n%i==0: lt.add(i) lt.add(n//i) for i in lt: for j in lt: for k in lt: if i*j*k ==n: out+=1 print(out) #2430
路径
开始想用Floyd解法,发现要跑很久,后面参考大佬博客学习了一下DP(动态规划)。
思路:
lcm(x,y)函数用于返回x和y的最小公倍数
列表out中存放最短距离,例如out[i]是从节点1到节点i的最短距离,当i在[1,22]范围时,out[i]=i.
但是从i=23开始,就有out[i]=min(out[i-1]+lcm(i-1,i),out[i-2]+lcm(i-2,i),…out[i-20]+lcm(i-20,i),out[i-21]+lcm(i-21,i))
以此类推,一直算到out[2021]即可
out = [0]*2022 def gcd(x,y): #最大公约数 if y==0: return x return gcd(y,x%y) def lcm(x,y): #最小公倍数 g=gcd(x,y) return x*y//g for i in range(1,2022): d = 21 #间隔 if i < 23: out[i] = i else: out[i] = out[i-d] + lcm(i-d,i) while d: if out[i-d]+lcm(i-d,i) < out[i]: out[i] = out[i-d] + lcm(i-d,i) d -= 1 print(out[2021])
程序设计
时间显示
n=input() x=int(n[:-3])%(3600*24) h,d=divmod(x,3600) m,s=divmod(d,60) print("{}:{}:{}".format(str(h).zfill(2),str(m).zfill(2),str(s).zfill(2)))
砝码称重
我最初的想法是给每一个砝码质量分配一个系数k,k的值是[1,0,-1]
的其中之一,每一个质量乘上系数k之后放在同一侧,看共有多少个可能性,但是太繁琐了…
看了下大佬们的思路发现这题也可以DP,思路就是定义二维数组f[i][j]
,i是砝码数量,j是总重量,如果用i个砝码可以称出重量j,则f[i][j]=1
。每加入一个新砝码(重为x),则有:
f[i][x] = 1 同时若用i-1个砝码可以称出重量j,则用i个砝码也可以称出重量j,即f[i][j] = f[i-1][j] 在已有组合的基础上,在天平左右各放一次新砝码,即f[i][j+x]=1、f[i][abs(j-x)]=1
最后统计f[n-1]中1的个数即可,最后两个测试点超时了
n=int(input()) count=0 _max = 0 #能称出的最大重量 a=list(map(int,input().split())) #存放每个砝码的质量 for i in a: _max += i f = [[0]*2*_max for i in range(n+1)] #用于dp的数组 f[0][a[0]] = 1 #f[i][j]的值为1代表用i个砝码可以称出质量j for i in range(1,n): x = a[i] #当前加入砝码的质量 f[i][x] = 1 for j in range(1,_max+1): if f[i-1][j]: f[i][j] = f[i-1][j] #i-1个砝码能称出的质量i个砝码也可以 for j in range(1,_max+1): if f[i-1][j]: #在前一状态的基础上进行新砝码的摆放 f[i][j+x]=1 f[i][abs(j-x)]=1 #统计 for i in range(1,_max+1): if f[n-1][i]: count += 1 print(count)
杨辉三角形
自己写老是超时,参考y神博客写的,大佬的思路真的强…
n=int(input()) def c(a,b): res = 1 i = a for j in range(1,b+1): res = res * i / j if res > n: return res i -= 1 return res def check(k): l = 2 * k r = max(n,l) while l<r: mid = l + r >>1 if c(mid,k) >= n: r = mid else: l = mid +1 if c(r,k) != n: return False print(int(r*(r+1)/2+k+1)) return True for i in range(16,0,-1): if check(i): break
括号序列
可以用DP做,合法的括号序列需要满足两个条件:
1.左右括号数相同
2.任意前缀中左括号数不小于右括号数
结合这两个条件,可以先用count来表示左括号比右括号多多少个
,遍历一遍括号序列,当遇到左括号,count+=1
,否则count-=1。当count<0时不满足第二个条件,需要添加一个左括号,同时count+=1,最后得到count的值就是需要添加右括号的个数
。
然后定义二维数组f[i][j]
为前i个括号中,左括号比右括号多j个的方案数.因而有f[i][j]=f[i-1][j+1]+f[i][j-1]
具体思路看y神博客
这篇关于第十二届蓝桥杯省赛B组 做题记录(python)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-03用FastAPI掌握Python异步IO:轻松实现高并发网络请求处理
- 2025-01-02封装学习:Python面向对象编程基础教程
- 2024-12-28Python编程基础教程
- 2024-12-27Python编程入门指南
- 2024-12-27Python编程基础
- 2024-12-27Python编程基础教程
- 2024-12-27Python编程基础指南
- 2024-12-24Python编程入门指南
- 2024-12-24Python编程基础入门
- 2024-12-24Python编程基础:变量与数据类型