打表法

打表法

1.情景分析

当遇到某些问题,已经求得数列的一部分时,要求给定任意项的下标,返回该项的权值。

比如现在有一个数列:1,4,9,16,25,…

2.处理思路

主要有2种题型:

  1. 一种是要求推导出通项的题目,这类题目需要推导出前几项,然后根据前几项得到通项公式 f ( x ) f(x) f(x),最后根据通式预测 f ( k ) f(k) f(k),见:ICPC 2017 南宁区域赛L. Twice Equation
  2. 另一种是存在的答案本身就很少,比如给定的n是 1 0 18 10^{18} 1018,但是当 n > = 100000 n >= 100000 n>=100000后,就 不存在答案 或者答案 非常稀疏,这类题目就需要将全部的表给打出来,因为表本身就非常少,见:ICPC 2016 北京区域赛 K - JiLi Number

对于预测的推导通式的题型 f ( x ) f(x) f(x),这里给出一些推导 f ( x ) f(x) f(x)的方法。

2.1 观察法

2.1.1 普通性质

对于比较简单的算式,可以直接发现其性质:比如给定数列:1, 2, 4, 8, …我可以清楚地知道它就是2的幂次方。

2.1.2 特殊数列

给定的数列是一些特殊数列的前几项,比如:

斐波那契数列:0, 1, 1, 2, 3, 5, 8

哈代-拉马努金数列:1, 1, 2, 3, 5, 7, 11, 15

卡特兰数:1, 1, 2, 5, 14, 42, 132

2.2 插值法

2.2.1 差分法

对于一个数列:1, 2, 4, 10, 23, 46, 82, …

它的一阶数列为:1, 2, 6, 13, 36, …

它的二阶数列为:1, 4, 7, 10, 13, …

它的三阶数列为:3, 3, 3, 3, …

发现三阶数列为常数列,因此原数列1, 2, 4, 10, 23, 46就被称为三阶等差数列。每一个高阶等差数列都有一个多项式的通项公式。

将所有的序列写为如下的形式:

C n 1        a 1        a 2        a 3        a 4        a 5        . . . C_{n}^1\ \ \ \ \ \ a_1\ \ \ \ \ \ a_2\ \ \ \ \ \ a_3\ \ \ \ \ \ a_4\ \ \ \ \ \ a_5\ \ \ \ \ \ ... Cn1      a1      a2      a3      a4      a5      ...

C n 2             b 1         b 2         b 3         b 4         . . . C_n^2\ \ \ \ \ \ \ \ \ \ \ b_1\ \ \ \ \ \ \ b_2\ \ \ \ \ \ \ b_3\ \ \ \ \ \ \ b_4\ \ \ \ \ \ \ ... Cn2           b1       b2       b3       b4       ...

C n 3                  c 1          c 2          c 3          . . . C_n^3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ c_1\ \ \ \ \ \ \ \ c_2\ \ \ \ \ \ \ \ c_3\ \ \ \ \ \ \ \ ... Cn3                c1        c2        c3        ...

. . .                  . . .                  . . .                  . . . ...\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ...\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ...\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ... ...                ...                ...                ...

C n m                       0          0          . . . C_n^m\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 0\ \ \ \ \ \ \ \ 0\ \ \ \ \ \ \ \ ... Cnm                     0        0        ...

有如下性质

  1. 序列的第 n n n a n a_n an为: a n = a 1 + b 1 C n − 1 1 + c 1 C n − 1 2 + . . . + 0 C n − 1 m a_n = a_1 + b_1C_{n-1}^1 + c_1C_{n-1}^2+...+0C_{n-1}^m an=a1+b1Cn11+c1Cn12+...+0Cn1m
  2. 序列的前缀和 S n S_n Sn为: S n = a 1 C n 1 + b 1 C n 2 + c 1 C n 2 + . . . + 0 C n m S_n = a_1C_n^1 + b_1C_n^2 + c_1C_n^2 + ... + 0C_n^m Sn=a1Cn1+b1Cn2+c1Cn2+...+0Cnm

当然, a n a_n an也可以由 S n − S n − 1 S_n - S_{n-1} SnSn1得到

例如:

序列:1, 4, 9, 16, 25

C n 1        1        4        9        16        25        . . . C_{n}^1\ \ \ \ \ \ 1\ \ \ \ \ \ 4\ \ \ \ \ \ 9\ \ \ \ \ \ 16\ \ \ \ \ \ 25\ \ \ \ \ \ ... Cn1      1      4      9      16      25      ...

C n 2             3         5         7         9         . . . C_n^2 \ \ \ \ \ \ \ \ \ \ \ 3\ \ \ \ \ \ \ 5\ \ \ \ \ \ \ 7\ \ \ \ \ \ \ 9\ \ \ \ \ \ \ ... Cn2           3       5       7       9       ...

C n 3                  2          2          2          . . . C_n^3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2\ \ \ \ \ \ \ \ 2\ \ \ \ \ \ \ \ 2\ \ \ \ \ \ \ \ ... Cn3                2        2        2        ...

. . .                  . . .                  . . .                  . . . ...\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ...\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ...\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ... ...                ...                ...                ...

C n m                      0          0          . . . C_n^m\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 0\ \ \ \ \ \ \ \ 0\ \ \ \ \ \ \ \ ... Cnm                    0        0        ...

那么有:

a n = 1 + 3 C n − 1 1 + 2 C n − 1 2 = n 2 a_n = 1 + 3C_{n-1}^1 + 2C_{n-1}^2 = n^2 an=1+3Cn11+2Cn12=n2

S n = C n 1 + 3 C n 2 + 2 C n 3 = n ( n + 1 ) ( 2 n + 1 ) 6 S_n = C_n^1 + 3C_n^2 + 2C_n^3 = \frac{n(n+1)(2n+1)}{6} Sn=Cn1+3Cn2+2Cn3=6n(n+1)(2n+1)

2.2.2 高斯消元法

对于一个 r r r阶高次等差数列,我们可以设其有一个对应的多项式: f ( x ) = a ∗ x r + b ∗ x r − 1 + c ∗ x r − 2 + . . . + t f(x) = a*x^r + b*x^{r - 1} + c * x^{r-2}+...+t f(x)=axr+bxr1+cxr2+...+t,然后带入 r + 1 r + 1 r+1个点,即可得到 r + 1 r+1 r+1个方程,通过高斯消元解方程,即可得到所有的系数 a 、 b 、 c 、 . . . a、b、c、... abc...,从而得到多项式的方程。

例如数列:1, 5, 15, 35, 70, 126, 210。

进行差分可以得到:

2.2.3 拉格朗日插值法

可以直接带入拉格朗日插值法公式:

f ( x ) = ∑ i = 1 n y i ∏ j ≠ i x − x j x i − x j f(x)=\sum_{i=1}^{n} y_i\prod_{j\neq i }\frac{x-x_j}{x_i-x_j} f(x)=i=1nyij=ixixjxxj

从而得到特定点的 f ( k ) f(k) f(k):

f ( k ) = ∑ i = 1 n y i ∏ j ≠ i k − x j x i − x j f(k)=\sum_{i=1}^{n} y_i\prod_{j\neq i }\frac{k-x_j}{x_i-x_j} f(k)=i=1nyij=ixixjkxj

2.3 暴力线性递推方程

对于一些数列,它可能和前面的几项数列都有关系,可能是线性递推式子,例如 f ( i ) = a f ( i − 1 ) + b f ( i − 2 ) + c f ( i − 3 ) + . . . + t f(i) = af(i - 1) + bf(i - 2) + cf(i - 3) + ... + t f(i)=af(i1)+bf(i2)+cf(i3)+...+t,那么可以暴力枚举所有的系数,一般来说,我们设 f [ i ] = a ∗ f [ i − 3 ] + b ∗ f [ i − 2 ] + c ∗ f [ i − 1 ] + d f[i] = a * f[i - 3] + b * f[i - 2] + c * f[i - 1] + d f[i]=af[i3]+bf[i2]+cf[i1]+d, 如果不够再增加长度。

例如:icpc 2017 南宁区域赛L. Twice Equation

得到数列:0 3 20 119 696 4059 23660 137903 803760 4684659 27304196 159140519。使用暴力枚举线性递推的系数,系数从-100枚举到100,暴力代码如下:

#include <bits/stdc++.h>

using namespace std;

int const N = 2e5 + 10;
typedef long long LL;

int n, T, m;

int main() {
    for (int a = -100; a <= 100; ++a) {
        for (int b = -100; b <= 100; ++b) {
            for (int c = -100; c <=100; ++c) {
                for (int d = -100; d <= 100; ++d) {
                // 0 3 20 119 696 4059 23660 137903 803760 4684659 27304196 159140519
                // f[i] = a * f[i - 3] + b * f[i - 2] + c * f[i - 1] + d
                    if (696 == 3 * a + 20 * b + 119 * c + d && 119 == 3 * b + 20 * c + d && 4059 == 20 * a + 119 * b + c * 696 + d && 23660 == 4059 * c + 696 * b + 119 * a + d) {

                        if (137903 == 696 * a + 4059 * b + 23660 * c + d)
                            if (803760 == 4059 * a + 23660 * b + 137903 * c + d)
                                if (4684659 == 803760 * c + 137903 * b + 23660 * a + d)
                                    if (27304196 == 4684659 * c + 803760 * b + 137903 * a + d)
                                        if (159140519 == 27304196 * c + 4684659 * b + 803760 * a + d)
                                            cout << a << " " << b << " " << c << " " << d << endl;
                    }
                        

                }
            }
        }
    }
    return 0;
}

打出来一个式子的系数为:0 -1 6 2(当然其他的系数也可以,比如:1 -7 7 0),所对应的式子是: f [ i ] = 6 ∗ f [ i − 1 ] − f [ i − 2 ] + 2 f[i] = 6 * f[i - 1] - f[i - 2] + 2 f[i]=6f[i1]f[i2]+2(或者: f [ i ] = f [ i − 3 ] − 7 f [ i − 2 ] + 7 f [ i − 1 ] f[i] = f[i - 3] - 7f[i - 2] + 7f[i - 1] f[i]=f[i3]7f[i2]+7f[i1])。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值