“相邻两个数相加”得到下一个数,典型的杨辉三角。杨辉三角第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分还不错,结束