前言
今天上午去献血啦!在成都市血液中心,待遇很好,体检通过后先发了一些食物,防止一会饿或者来之前空腹的童鞋。可以看出吃的还是比较不错的,正常的早饭也不会吃那么多,但是泡面的油包不能放,水是甜的加了糖之类的,面包不太好吃,就是纯面包,吃不了可以带着,后面才知道没吃饱也可以再加,嘻嘻。
体检的时候会给免费测一次血常规,里面参数大家就找个对照表比对一下吧,有没有专业人士帮我看下我的学业状况(#.#),我献的是血小板,据说三天内可以恢复到之前状态,并在14天内不能继续献血。
好了扯了这么多,回到正题,距离今年省赛还有5天,我作为一个普通学生,选择继续刷真题,同时也希望大家相互帮助,相互学习,合作共赢嘛!
A:卡片
首先我们思考一下,那个数字消耗的最快,从1开始,当然1最快耗光,所以我们只要在每个数字中查找1的数量,累计起来当达到2022时break
num=0
for i in range(1,10000):
num+=str(i).count("1")
if num>2021:
break
print(i-1)//当前数字未能完全拼出,所以i-1
B:直线
这题还是比较简单,要我们求这些点一共能组成多少种直线,就是不同斜率和截距,我们可以把这两个参数变成一个元素,用set存储起来不会重复,最后集合的长度就是解。
points=[[x,y] for x in range(20) for y in range(21)]//先建表
arr=set()
for i in points:
x1,y1=i[0],i[1]
for j in points:
x2,y2=j[0],j[1]
if x1==x2://横坐标相同就是垂直,没有斜率后面加
continue
k=(y2-y1)/(x2-x1)
b=(x2*y1-x1*y2)/(x2-x1)
if (k,b) not in arr://不在就加进去
arr.add((k,b))
print(len(arr)+20)
C:货物摆放
这题主打一个找因子,n%两个因子的乘积==0,就说明符合条件,可以用1凑第三个数嘛,注意读题,不是要求必须正方形,n=L * W * H
n=2021041820210418
l=[]
i=2
x=n
while i<pow(x+1,0.5)://求因数
if x%i==0:
l.append(i)
x//=i
else:
i+=1
l.append(x)
s=set()
s.add(1)
for j in l:
p=set()
for k in s:
p.add(j*k)//求因子,最小是1*2=2
for k in p:
s.add(k)
count=0
for k1 in s:
for k2 in s:
if n%(k1*k2)==0:
count+=1
print(count)
D:路径
E:回路计数
这到题我看网上用二进制计算到达与否关系的方法较多,一开始看的很晕,我尝试解释一下,如果哪里有问题欢迎大家comment。
topic:从1号教学楼开始,访问完每一栋教学楼一次,又回到一号教学楼的不同方案
1.状态压缩+DP
每一栋教学楼分为访问和不访问,可以用0,1表示,访问完所有的教学楼就用21个1表示。
2.动态规划:划分子问题
原问题:访问玩每栋教学楼又回到一号楼的不同方案,所有的楼都可以回到1号教学楼,因为1和所有都互质,最后一次可以在2-21号楼,在这基础上,再次划分子问题,如果最后一次访问的是2号楼,它可以由上一次所在的教学楼方案数之和得到
3.状态转移方程
dp[ i + (1 << k) ][ k ] += dp[ i ][ j ];
k一定要在状态i中,并且k和j要有通路,j是最后访问的,dp[ i ][ j ]表示从状态 i 到 j 的路径数,原状态 i 在楼 j 已经访问过的情况下,尝试将楼 k 加入已访问的点。说白了就是去回溯j的上一层都有啥。
4.初始状态
dp[1][0] = 1,只访问1号楼,且当前所在教学楼为1的方案,只有一种。
import math
n=21
state=1<<21
Map=[[0]*(n+1) for i in range(n+1)]
dp=[[0]*n for i in range(state)]
dp[1][0]=1
for i in range(n+1):
for j in range(n+1):
if math.gcd(i,j)==1:
Map[i][j]=1
for i in range(state):
for j in range(n)://当前是第几栋楼
if i>>j&1://这栋楼来没来过
for k in range(n)://来过就判断这栋和它上一层的关系
if Map[k+1][j+1]==1 and i>>k&1://有通路并且有路来
dp[i][j]+=dp[i-(1<<j)][k]//累加起来
print(sum(dp[-1])-dp[-1][0])
F:时间显示
回去把datetime库玩两遍,送分题可不能丢,因为他输入的是一个毫秒数,所以用delta把单位换一下,delta更像是一个增量单位,他输入的是微秒数乘以微秒单位就是一个时间段。
from datetime import datetime, timedelta
start = datetime(year=1970, month=1, day=1)
dela = timedelta(milliseconds=1)
now = int(input())
now = start + now * dela
print('%02d:%02d:%02d' % (now.hour, now.minute, now.second))
G:杨辉三角形
大名鼎鼎的杨辉三角来啦!这道题可以写程序也可以找规律,当然前提是有点奥数基础。
想了半天,自己理解的还是不太好,这里就不贴代码了,大家自己搜索一下资料吧。
H:左孩子右兄弟
这题要求数层数,我们可以用DP的方法,记住当前层个数,和孩子节点中层数最多的。
因为我们考虑的是最大层数,根节点是0层,他的孩子可以全部算上,然后求一个孩子节点中层数最多的方法,就是答案。
import sys
sys.setrecursionlimit(100000) #设置最大递归深度
n = int(input())
A = [[] for i in range(n + 1)] #根是从索引1开始,所以索引0就不用了,开n加1个位置
#构建二叉树存储输入的值
for i in range(2, n + 1):
v = int(input()) #先接收位置,相同层的放在一起
A[v].append(i) #把节点加到输入的那一层中去
#深度优先搜索与动态规划
def dfs(i):
if A[i] is None: #叶子节点,高度为0
return 0
maxn = 0
for j in A[i]: #以i为父节点的所有子节点的二叉树的高度最大值
maxn = max(maxn, dfs(j)) #以i为节点形成的所有二叉树的高度最大值
return len(A[i]) + maxn #孩子节点的个数 + 以孩子节点为根节点构成二叉树的高度最大值
print(dfs(1)) #以1作为根节点二叉树的最高的高度
最后两道题我之前的博客里面写过,这里就不仔细说了。
结语
这届真题总的来看难度还是适中的,5道填空题好评,就是数字有点大,编程题的前3道需要仔细读题思考,多测试,多手敲,少看题解代码,最后3天截断代码依赖,自己手敲两套练练。
最后也给献血旅程做个总结,我献的一个测试量(最多两个),耗时52分钟,加上前面体测、吃东西,以及器材安装和拆卸,可以说时间还是蛮久的,痛感嘛就还好,运行的时候是没什么感觉的,躺在那里休息就好,五十分钟也够刷一集剧了。
有趣的是当我在那躺着,血液中心的一个领导样貌的工作人员还给我送了一个赠品(笔记本),because I’m student,送我!
拆卸之后就出去领献血证以及献后食物,我建议大家一边吃一边排献血证,后面人有点多,而且这种地方的机器反应你懂得。。
当然啦吃的还不错,食物是新鲜的,这也是个缓冲区,防止没有位置献血。
最后贴一个献血前后注意事项吧,我只能说大家量力而行,一个测试量有150元的补助,但是花费的时间还是很久的,从学校坐车来和回去一共花了5小时,到家后浑身腰酸背痛,睡眠质量都提升了,这次的blog就到这里吧,离蓝桥杯还有4天,大家放松心态,记得提前打印准考证,刷刷真题和模板,我们赛后再见!