📅  最后修改于: 2023-12-03 14:54:36.229000             🧑  作者: Mango
如果给定一个数列的前几项,如何找到接下来的N个项呢?一种常见的方法是找到数列的通项公式,然后通过公式计算出后续的项。这里介绍两种方法。
已知数列的前几项,我们可以通过暴力搜索找到通项公式。具体地,我们可以尝试用不同的次数对前几项进行多项式拟合,然后选取拟合效果最好的多项式作为通项公式。这里提供一个Python代码片段:
import numpy as np
def find_formula_naive(sequence):
"""
通过暴力搜索找到数列的通项公式
Args:
- sequence: list[int],已知数列的前几项
Returns:
- formula: str,数列的通项公式
"""
def gen_matrix(x, n):
"""
生成矩阵X
Args:
- x: list[float],自变量
- n: int,多项式次数
Returns:
- X: np.ndarray,矩阵X
"""
m = len(x)
X = np.zeros((m, n+1))
for i in range(m):
for j in range(n+1):
X[i,j] = x[i]**j
return X
def fit(X, y):
"""
多项式拟合
Args:
- X: np.ndarray,自变量矩阵
- y: np.ndarray,因变量
Returns:
- w: np.ndarray,多项式系数
- mse: float,均方误差
"""
w = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y)
y_hat = X.dot(w)
mse = np.mean((y_hat - y)**2)
return w, mse
for n in range(1, len(sequence)):
X = gen_matrix(list(range(n)), n-1)
w, mse = fit(X, sequence[:n])
if mse < 1e-10:
formula = ' + '.join([f'{w[i]:+.2f}n^{i}' for i in range(n)])
return formula
formula = '未找到合适的多项式'
return formula
这里假设数列的通项公式是一个多项式,并采用均方误差作为拟合效果的评价指标。代码会从多项式次数为1开始,依次增加多项式次数,直到找到一个均方误差小于某个极小值的多项式为止。
另一种方法是利用数列的差分性质。如果把数列的前缀差分,得到一个新的数列,那么新数列的第n项就是原数列的第n+1项减去第n项。如果再将新数列进行前缀差分,就得到新的新数列,依次类推,直到得到一个全为0的数列。最终得到的是一个二维数组,它的每一行都是差分后得到的一列数列。如果我们能找到每一列数列的通项公式,那么就可以通过反复求和得到原数列的通项公式。
以下是一个Python代码片段:
def differ(sequence):
"""
差分操作
Args:
- sequence: list[int],输入数列
Returns:
- list[int],差分得到的新数列
"""
return [sequence[i+1] - sequence[i] for i in range(len(sequence)-1)]
def find_formula_by_diff(sequence):
"""
通过差分法找到数列的通项公式
Args:
- sequence: list[int],已知数列的前几项
Returns:
- formula: str,数列的通项公式
"""
def find_formula_by_diff_helper(array):
"""
递归查找每一列的通项公式
Args:
- array: np.ndarray,二维数组,每一行是差分后得到的一列数列
Returns:
- formula: str,该列数列的通项公式
"""
if np.std(array) == 0:
return str(array[0,0])
n, m = array.shape
x = list(range(1, n+1))
X = gen_matrix(x, m-1)
y = array[:,0]
w, mse = fit(X, y)
if mse > 1e-10:
return '未找到合适的多项式'
formula = ' + '.join([f'{w[i]:+.2f}n^{i}' for i in range(m-1)])
prefix = f'{w[0]:+.2f}'
suffix = find_formula_by_diff_helper(array[:,1:])
if suffix.startswith('-'):
formula += suffix
else:
formula += ' + ' + suffix
if prefix == '+1.00':
formula = formula.lstrip('+')
elif prefix == '-1.00':
formula = '-' + formula.lstrip('+')
else:
formula = f'{prefix}({formula})'
return formula
curr = sequence
array = np.array([curr])
while True:
curr = differ(curr)
if len(curr) == 0:
break
array = np.concatenate((array, [curr]), axis=0)
formula = find_formula_by_diff_helper(array)
return formula
这里定义了一个差分函数differ
和一个差分法的求解函数find_formula_by_diff
。find_formula_by_diff
会先调用differ
函数对输入的数列做差分操作,然后将得到的新数列追加到一个二维数组中。接下来,它会不断对最后一列做差分,直到得到一个全为0的数列。最终得到的是一个二维数组,它的每一行都是差分后得到的一列数列。find_formula_by_diff_helper
是一个递归函数,用于递归求解每一列数列的通项公式。在求解每一列数列的通项公式时,我们需要用到多项式拟合。需要注意的是,每一列数列的长度可能不相同,因此要在拟合时使用不同的自变量。此外,当一列数列的最高项系数为1或-1时,应该省略该项的系数。