“相邻两个数相加”得到下一个数,典型的杨辉三角。杨辉三角第4层为:contribute = [1, 3, 3, 1]
记输出weight = [3, 1, 2, 4],用线性代数的知识可得:contribute @ weight.T = 16
所以基本的思路就是:
1. 利用整数n求出杨辉三角第n层,记为contribute
2. 从字典序最小的序列开始枚举,验证输出是否满足条件
利用杨辉三角每个数都是组合数的性质,写出这个函数求contribute
def Pascal_triangle(num):
""" 杨辉三角"""
basic = 1
cont = [basic]
ele, is_even = divmod(num + 1, 2)
# ele为不重复元素的边界
for idx in range(1, ele):
basic *= (num - idx) / idx
cont.append(round(basic))
if is_even:
mirror = reversed(cont)
# 偶数行: 无需回溯
else:
mirror = reversed(cont[:-1])
# 奇数行: 需回溯
cont.extend(mirror)
return cont
num代表的是第n层
字典序初始化为:list(range(1, n + 1)),求下一个字典序的函数为:
def next_permutation(seq):
""" 找到下个字典序
exp: 8 3 7 6 5 4 2 1
| | """
n = len(seq)
left = -1
for idx in range(n - 2, -1, -1):
if seq[idx] < seq[idx + 1]:
# 找到顺序区的右边界
left = idx
break
if left != -1:
left_val = seq[left]
for right in range(n - 1, left, -1):
right_val = seq[right]
if left_val < right_val:
# 找到交换位
seq[left] = right_val
seq[right] = left_val
seq[left + 1:] = reversed(seq[left + 1:])
# 逆转逆序区
return seq
以 [8, 3, 7, 6, 5, 4, 2, 1] 为例,这个函数完成的工作就是:
1. 从右到左开始查找,因为3 < 右边第一个数,所以记3的索引为left
2. 从右到左开始查找比3大的数,得到4的索引记为right
3. 交换left和right对应的数,此时序列变为 [8, 4, 7, 6, 5, 3, 2, 1]
4. 可以看到left右侧全是逆序的 (即4的右侧),所以逆转 seq[left + 1: ] 得到 [8, 4, 1, 2, 3, 5, 6, 7]
利用这个函数就可以枚举输出,每个输出记为weight。因为蓝桥杯是不支持numpy的,所以用这个函数验证:
def cal(order):
return sum([m * n for m, n in zip(order, contribute)]) == summary
90分还不错,结束