📌  相关文章
📜  找到系列2、15、41、80、132的N个项。(1)

📅  最后修改于: 2023-12-03 14:54:36.229000             🧑  作者: Mango

找到系列2、15、41、80、132的N个项

如果给定一个数列的前几项,如何找到接下来的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_difffind_formula_by_diff会先调用differ函数对输入的数列做差分操作,然后将得到的新数列追加到一个二维数组中。接下来,它会不断对最后一列做差分,直到得到一个全为0的数列。最终得到的是一个二维数组,它的每一行都是差分后得到的一列数列。find_formula_by_diff_helper是一个递归函数,用于递归求解每一列数列的通项公式。在求解每一列数列的通项公式时,我们需要用到多项式拟合。需要注意的是,每一列数列的长度可能不相同,因此要在拟合时使用不同的自变量。此外,当一列数列的最高项系数为1或-1时,应该省略该项的系数。