无
def get_cot(num):
"""
:param num: 要拼的数字
:return: 组成该数字各位数的个数
"""
cot_dict = {
}
while num != 0:
tail = num % 10
if tail not in cot_dict:
cot_dict[tail] = 1
else:
cot_dict[tail] += 1
num //= 10
return cot_dict
if __name__ == '__main__':
have_dict = {
}
for i in range(10):
tmp_cot = int(input(f"{i}有几张?"))
have_dict[i] = tmp_cot
now_num = 0
break_flag = 0
while True:
if break_flag == 1:
break
now_num += 1
cot_dict = get_cot(now_num)
for key in cot_dict:
cot = cot_dict[key]
if have_dict[key] >= cot:
have_dict[key] -= cot
else:
break_flag = 1
break
print(now_num - 1) # 因为now_num不够了,所以break了,所以最多now_num-1
答案:
>>>0有几张? 2021
>>>1有几张? 2021
>>>2有几张? 2021
>>>3有几张? 2021
>>>4有几张? 2021
>>>5有几张? 2021
>>>6有几张? 2021
>>>7有几张? 2021
>>>8有几张? 2021
>>>9有几张? 2021
>>>3181
def get_k_b(dot1, dot2):
"""
:param dot1: 第一个点(当前遍历到的)
:param dot2: 第二个点(之前的)
:return: (k,b) if x1 - x2 != 0 else ('inf',x1)
"""
x1, y1 = dot1
x2, y2 = dot2
k, b = None, None
if x1 == x2:
k = float('inf')
b = x1 # k不存在时,通过b来确定唯一直线
else:
'''
y1 = kx1 + b
y2 = kx2 + b
∴ k = (y1-y2) / (x1-x2) b = (x1y2-x2y1) / (x1-x2)
'''
k = (y1-y2) / (x1-x2)
b = (x1 * y2 - x2 * y1) / (x1 - x2)
return (k, b)
if __name__== '__main__':
X_cot, Y_cot = map(int, input().split())
dot_lst = []
k_b_lst = []
ans = 0
# 初始化第0行
for x in range(X_cot):
dot_lst.append((x, 0))
k_b_lst.append((0,0))
ans += 1
# 从第1行开始
for x in range(X_cot):
for y in range(1, Y_cot):
now_dot = (x, y)
for pre_dot in dot_lst:
k_b = get_k_b(now_dot, pre_dot)
if k_b not in k_b_lst:
k_b_lst.append(k_b)
ans += 1
dot_lst.append(now_dot)
print(ans)
答案:
20 21
40257
import math
def get_fac(num):
"""
:param num: 待求因数的数
:return: 因数列表
"""
fac_num = []
for i in range(1, int(math.sqrt(num))+1):
if num % i == 0:
fac_num.append(i)
fac_num.append(num // i)
return fac_num
if __name__ == '__main__':
n = int(input())
### dp[i][j]
### i 代表货物数 ,j: 0 代表长; 1 代表宽; 2 代表高
dp = [[ 0 for i in range(n + 1)] for j in range(3)]
fac_dict = {
} # 避免重复计算
# 初始化:仅考虑长时,无论多少货物数,仅有1种方案
n_fac_lst = get_fac(n)
for n_fac in n_fac_lst:
dp[0][n_fac] = 1
# 从考虑宽开始
for j in range(1, 3):
for i in n_fac_lst: # 这里没写for i in range(1, n+1),因为所有可能出现的i一定是n的因数
i_fac_lst = get_fac(i)
for fac in i_fac_lst:
dp[j][i] += dp[j-1][i//fac]
print(dp[2][n])
内存不够
思路2:
DP+空间压缩
代码2:
import math
def get_fac(num):
"""
:param num: 待求因数的数
:return: 因数列表
"""
fac_num = []
for i in range(1, int(math.sqrt(num))+1):
if num % i == 0:
fac_num.append(i)
fac_num.append(num // i)
return fac_num
if __name__ == '__main__':
n = int(input())
### dp[i][j]
### i 代表货物数 ,j: 0 代表长; 1 代表宽; 2 代表高
dp = [0 for i in range(n + 1)]
fac_dict = {
} # 避免重复计算
# 初始化:仅考虑长时,无论多少货物数,仅有1种方案
n_fac_lst = get_fac(n)
for n_fac in n_fac_lst:
dp[n_fac] = 1
# 从考虑宽开始
for j in range(1, 3):
for i in n_fac_lst[::-1]: # 从后往前遍历,否则上一行的值会被更新
i_fac_lst = get_fac(i)
for fac in i_fac_lst[1:]: # 因数1不需要,因为dp[i]本身就是
dp[i] += dp[i//fac]
print(dp[n])
内存还是不够…用dp存似乎不合适
思路3:
暴力。求因数的函数更新了一下…原来没有用math.sqrt…
代码:
import math
def get_fac(num):
"""
:param num: 待求因数的数
:return: 因数列表
"""
fac_num = []
for i in range(1, int(math.sqrt(num))+1):
if num % i == 0:
fac_num.append(i)
fac_num.append(num // i)
return fac_num
if __name__ == '__main__':
ans = 0
n = int(input())
n_fac_lst = get_fac(n)
for i in n_fac_lst:
for j in n_fac_lst:
for k in n_fac_lst:
if i * j * k == n:
ans += 1
print(ans)
答案:
2021041820210418
2430
def get_LCM(a, b):
"""
:param a: 数a
:param b: 数b
:return: 最小公倍数
"""
large, small = None, None
if a > b:
large = a
small = b
else:
large = b
small = a
k = 1
while True:
if (small * k) % large == 0:
return small * k
k += 1
def get_nb_node(now_node, num):
"""
:param now_node: 当前节点
:param num: 总节点数
:return: 当前节点的邻接节点
"""
nb_lst = []
for k in range(-1, -22, -1):
nb_node = now_node + k
if nb_node < 1:
break
nb_lst.append(nb_node)
for k in range(1, 22):
nb_node = now_node + k
if nb_node > num:
break
nb_lst.append(nb_node)
return nb_lst
def build_graph(num):
"""
:param num: 总节点树
:return: 邻接矩阵
"""
graph = [ [float('inf') for i in range(num + 1)] for j in range(num + 1)]
for now_node in range(1, num + 1):
neighbour_node_lst = get_nb_node(now_node, num)
for nb_node in neighbour_node_lst:
weight = get_LCM(now_node, nb_node)
graph[now_node][nb_node] = graph[nb_node][now_node] = weight
return graph
def dijkstra(start, end):
"""
:param start: 开始节点
:param end: 结束节点
:return: 最短距离
"""
num = len(graph) # true node num + 1
nearest_dis_lst = graph[start][::]
vis_lst = [0 for i in range(num)]
vis_lst[start] = 1
while True:
nearest_dis = float('inf')
nearest_node = None
for node in range(1, num):
if vis_lst[node] == 0:
if nearest_dis_lst[node] < nearest_dis:
nearest_dis = nearest_dis_lst[node]
nearest_node = node
if nearest_node == end:
return nearest_dis
if nearest_node == None:
return -1
vis_lst[nearest_node] = 1
for nb_node, nb_dis in enumerate(graph[nearest_node]):
if vis_lst[nb_node] == 0:
nearest_dis_lst[nb_node] = min(nearest_dis_lst[nb_node], nearest_dis + nb_dis)
return -1
if __name__ == '__main__':
node_num = int(input())
graph = build_graph(node_num)
print(dijkstra(start = 1, end = node_num))
答案:
2021
10266837
思路:
不会,有空补一份递归的代码(比赛时没有运行出来)
emmm我的ACM大佬朋友劝我不要研究了(???),他的思路是状压DP
思路:
无
代码:
def get_time(second):
"""
:param second: 描述
:return: 时、分、秒
"""
second %= (24 * 3600)
h = second // 3600
second %= 3600
m = second // 60
second %= 60
s = second
return h, m, s
if __name__ == '__main__':
s = int(input()) // 1000
hour, minute, second = get_time(s)
print("{0:0>2d}:{1:0>2d}:{2:0>2d}".format(hour, minute, second))
结果:
46800999
13:00:00
思路1:
一行一行模拟
代码:
略
答案:
肯定过不了
思路2:
每一行(从0开始)的最大值是组合数C_{layer}^{layer//2},所以想先确定行,再确定在该行的哪一个位置
代码:
def get_fac(start, end):
"""
:param start: 大数
:param end: 小数
:return: start * start -1 * .... end
"""
if (start, end) not in fac_dict:
ans = 1
for i in range(start, end - 1, -1):
ans *= i
fac_dict[(start, end)] = ans
return fac_dict[(start, end)]
def get_C(sub, super):
"""
:param sub: C的下标
:param super: C的上标
:return: C_{sub}^{super},排列组合数
"""
return get_fac(sub, super + 1) // get_fac(super, 1)
def get_max(layer):
"""
:param layer: 层数
:return: 层的最大数,也就是 C_{layer}^{layer//2}
"""
sub = layer
super = layer // 2
return get_C(sub, super)
def get_layer(num):
"""
:param num: 输入的数
:return: 最早出现在哪一层
"""
layer = 0
while True:
l_max = get_max(layer)
if l_max >= num:
return layer
layer += 1
return -1
if __name__ == '__main__':
num = int(input())
fac_dict = {
}
layer = get_layer(num)
# 之前层有多少个数字
pre_cot = (1 + layer) * layer // 2
# num在当前层处于哪一个位置
sub = layer
super = layer // 2
break_flag = 0
while True:
if break_flag == 1:
break
C = get_C(sub, super)
if C == num:
break_flag = 1
break
super -= 1
cot = pre_cot + super + 1
print(cot)
答案:
应该是算了太多次阶乘,比思路1还慢…
思路3:
参考求杨辉三角中元素首次出现位置【2021蓝桥杯】
代码:
def get_fac(start, end):
"""
:param start: 大数
:param end: 小数
:return: start * start -1 * .... end
"""
if (start, end) not in fac_dict:
ans = 1
for i in range(start, end - 1, -1):
ans *= i
fac_dict[(start, end)] = ans
return fac_dict[(start, end)]
def get_C(sub, super):
"""
:param sub: C的下标
:param super: C的上标
:return: C_{sub}^{super},排列组合数
"""
return get_fac(sub, super + 1) // get_fac(super, 1)
def get_index(pos, layer):
"""
:param pos: 当前行的位置
:param layer: 所在行
:return: 总的位置
"""
return (1 + layer) * layer // 2 + pos + 1
if __name__ == '__main__':
num = int(input())
fac_dict = {
}
# 内层行
index = 1
for pos in range(16, 1, -1):
if index != 1:
break
layer = 2 * pos
while True:
C = get_C(layer, pos)
if C > num:
break
elif C == num:
index = get_index(pos, layer)
break
layer += 1
# 外层行
if index == 1:
if num != 1:
index = get_index(pos=1, layer=num)
print(index)
答案:
1000000000
500000000500000002
思路:
DFS,对于当前的node,首先查看node的子节点有多少个,假设有n个,则以node为根的二叉树的高度最少有n。接着计算所有以node的子节点为根的二叉树的高度,选择高度最高的那一个节点放到最下面,从而使高度最大化,即,遍历node的子节点,进行递归,得到子节点的最大高度,再加上原来的n,就是答案。
代码:
def dfs(node):
"""
:param node: 根节点
:return: 根节点所构造的二叉树的最大高度
"""
n = len(child_lst[node]) # 至少为n
child_height = 0
for child_node in child_lst[node]:
child_height = max(child_height, dfs(child_node))
return n + child_height
if __name__ == '__main__':
N = int(input())
child_lst = [[] for i in range(N + 1)]
for i in range(2, N + 1):
parent = int(input())
child_lst[parent].append(i)
print(dfs(1))
答案:
5
1
1
1
2
4
依稀记得题中的a和b初始化是0?(当时没做到这儿,印象不深)
思路:
DP,但怎么表示状态呢?差不多的题目在力扣刷到过,但它的每一步只能从数列头或者尾选一个数字,那样的话就可以创建一个二维的dp,dp[i][j]表示i…j的数列,来做。这题中,每一步可以从剩下的数字中任意选取一个,不太知道怎么保存状态。