蓝桥杯python第二期模拟赛 python 题解
文章目录
题目1
思路:就是简单的IP地址的位数吧,计算机的常识,也就是255
答案:255
题目2
思路:首先这道题和之前不一样的点是,我们求的是公约数,没有说最大公约数,所以说gcd是没有用的。
然后仔细看看题目,我们说的是与2021的最大公约数,首先满足的条件就是,一定能被2021整除,所以先取出所有能被2021整除的数
然后再1-2021中判断,能不能被其中一个数小于他的数整除,如果可以,说明就是公约数。
答案:89
from math import gcd
cnt = 0
h = []
for i in range(2,2022):
if 2021%i == 0:
h.append(i)
for i in range(1,2022):
for x in h:
if x > i:
break
if i % x == 0 and 2021 % x == 0:
cnt += 1
## print(i,x)
break
print(cnt) # 答案:89
题目3
思路:其实对于我们来说,又是穷举了,但是这里涉及一个上界,我们多少穷举到多少好呢,我觉得有一个笨方法,我试了一下,比如首先上界设为100,得到一个答案,然后我们可以提高上界1000,如果发现答案又大了,说明上界没有到,那就继续加,发现我们的答案没变的时候,说明就到我们的上界了
但实际上是有方法的,首先知道平方差公式
- 平方差公式:a^2 - b^2 = (a+b)(a-b)
- 确定内层循环范围:b<a,即内层循环最大值不大于外层循环当前值
- 确定外层循环范围:b=a-1时取得最小正数,此时(a+b)(a-b)=(2a-1),令2a-1=2021,得到a的上限1011
所以上界为1011是最准确的
s = set()
for i in range(1012):
for j in range(i+1,1012):
x = j*j - i*i
if x not in s and 1<=x<=2021:
s.add(x)
print(len(s)) # 答案:1516
##print(s)
题目4
思路:这个的话,实际上就是哈夫曼树了,对我们的数进行一个编码操作,这个确实知识点还没复习到,大二数据结构学的了,也可以看看。首先我们可以画一个哈夫曼的图
根据这个图我们就可以对我们的数据进行编码了,这些都是基本的知识,就是去较多的剔除,这样我们编码的时候,长度较短,出现比较少,就可以有效减小编码长度。
按左树为0,右树为1编码:
c: 3 11000
d: 4 11001
a: 10 1101
e: 18 111
b: 20 10
f: 50 0
5*3+5*4+4*10+3*18+2*20+1*50=219
题目5
思路:简单来说,就是一个哈希表,最后统计最多的字符,直接暴力搜素嘻嘻
m = ['FFEEFEAAECFFBDBFBCDA',
'DACDEEDCCFFAFADEFBBA',
'FDCDDCDBFEFCEDDBFDBE',
'EFCAAEECEECDCDECADDC',
'DFAEACECFEADCBFECADF',
'DFBAAADCFAFFCEADFDDA',
'EAFAFFDEFECEDEEEDFBD',
'BFDDFFBCFACECEDCAFAF',
'EFAFCDBDCCBCCEADADAE',
'BAFBACACBFCBABFDAFBE',
'FCFDCFBCEDCEAFBCDBDD',
'BDEFCAAAACCFFCBBAAEE',
'CFEFCFDEEDCACDACECFF',
'BAAAFACDBFFAEFFCCCDB',
'FADDDBEBCBEEDDECFAFF',
'CDEAFBCBBCBAEDFDBEBB',
'BBABBFDECBCEFAABCBCF',
'FBDBACCFFABEAEBEACBB',
'DCBCCFADDCACFDEDECCC',
'BFAFCBFECAACAFBCFBAF']
from collections import Counter
c = Counter()
h = {}
for i,x in enumerate(m):
for j,y in enumerate(x):
h[y] = h.get(y,0) + 1
# c[y] += 1
print(max(h)) # 答案:F 出现了78次
题目6
思路:这个就是模拟题了,如果刚刚好是倍数,就买相应盒数,如果不是,那可能要多买一盒才能达到要求
p,t = map(int,input().split())
if t % 12==0:
print(p*(t//12))
else:
print(p*(t//12+1))
题目7
思路:勾股定理,binggo
a,b,c = map(int,input().split())
a,b,c = sorted([a,b,c])
if a*a + b*b == c*c:
print('YES')
else:
print('NO')
题目8
思路:这道题其实就是考一个图的连通分量,所以我们可以利用并查集
但是这道题我是有些不懂的,我们选小朋友,12中选一个,3选一个,456起码选择两个才知道所有秘密吧,不明白(可能知道秘密的可以互相交换吧)
后面好像明白了,就是4一直把秘密传给5,5传给6,6传给4,这样慢慢的,就互相知道秘密了
def find(x):
if x!=f[x]:
f[x] = find(f[x])
return f[x]
def union(x,y):
fx,fy = find(x),find(y)
if fx!=fy:
f[fx] = fy
n = int(input())
f = [i for i in range(n+1)]
a = map(int,input().split())
for i,v in enumerate(a):
union(i+1,v)
s = set()
for i in range(1,n+1):
x = find(i)
if x not in s:
s.add(x)
print(len(s))
题目9
思路:这道题把我搞蒙了,这道题实际上是一个杨辉三角形,DP真牛
我们可以这样想,如果我们有n个数,其中就是n//2个奇数,我们要放在n个位置上,所以就是组合问题了,最后的偶数的放法就只有一种了,是不是很简单,所以就是求 C n n / / 2 C_n^{n//2} Cnn//2,但是假设我们有1000个数,这样太大了,我们也要取模,所以就可以借鉴我们的杨辉三角形,因为杨辉三角形就是可以求组合数的。
其实我觉得,我们可以调库的,很简单,只要明白意思
n = int(input())
MOD = 1000000007
import math
print(math.comb(n,n//2)%MOD)
dp = [0]*1001
for i in range(1,n+1):
dp[0] = 1
dp[i] = 1
for j in range(i-1,0,-1):
dp[j] = (dp[j]+dp[j-1])%MOD
print(dp[n//2])
题目10
思路:这道题就是熟为人知的DFS了,其实我感觉用BFS也可以的,不过这里有几部分需要剪枝,剪枝才能得到更好的成绩的。
比如我们需要判断到当前路径的最优值,如果比最优值大了,说明这条路径不对,我们就可以直接剪枝剪掉,我们还可以判断如果当前就和最优的结果一样的话,那还没到终点就得到了这个值,后面肯定是大于等于的,所以我们也进行剪枝。
n,m = map(int,input().split())
g = []
for _ in range(n):
g.append([int(x) for x in input()])
f = [(1,0),(-1,0),(0,1),(0,-1)] # 上下左右
visit = [[0]*m for _ in range(n)]
temp = [[float('inf')]*m for _ in range(n)]
res = float('inf')
# dfs x,y是起点,t是已经经过了2,s是已有最少的经过2的次数
def dfs(x,y,t,s):
if x == n-1 and y == m-1:
global res
res = min(res,s)
return
if s < temp[x][y]:
temp[x][y] = s
else:
return
for tx,ty in f:
dx,dy = tx+x,ty+y
if 0<= dx < n and 0<= dy < m and visit[dx][dy]==0:
if g[dx][dy] == 2:
if t == 1: continue # 经过两次
if s == res: continue # 当前和最优相等,之后肯定是大于等于
visit[dx][dy] = 1
dfs(dx,dy,1,s + 1)
visit[dx][dy] = 0
else:
visit[dx][dy] = 1
dfs(dx,dy,0,s)
visit[dx][dy] = 0
visit[0][0] = 1
dfs(0,0,0,0)
if res == float('inf'):
print(-1)
else:
print(res)