0
点赞
收藏
分享

微信扫一扫

【一些常用的递推通项公式的求法】

1.前言:在很多题目里会涉及到递推公式的使用,然而大多数递推公式都是有很强的前后依赖性,第n项的求解依赖于n前边的几项。比如大名鼎鼎的fib数列。但是很多时候,我们要O(1)公式。本文简单的谈一下一些常见的递推公式的求解。

2.一阶线性递推。形如:

                                                         【一些常用的递推通项公式的求法】_递推

这种序列,显然是可以构造一个矩阵,然后利用矩阵快速幂求解。但是我们也可以求解它的通项公式。首先是特征方程:

我们把an,an-1,an-2分别看作二次项,一次项,和常数项。然后就可以得到一个一元二次方程:

                                                         【一些常用的递推通项公式的求法】_特征方程_02

我们把这个方程接一下,会得到两个根x1,x2。(这里在复数域下解方程)。然后通项公式:

                    【一些常用的递推通项公式的求法】_递推_03

在x1,x2是共轭复数时,采用复数的三角表示法给出。一般最常用的就是前两种。其中,A,B这些系数由前几项待定系数解出。

这样,其实就很轻松地推出了fib数理的通项公式。

   例题:​​南昌网赛H​​。其实这个题出的很棒,但是由于数据有点水导致很多错误解法AC。真实的做法就是:

                                                            【一些常用的递推通项公式的求法】_特征方程_04

然后找一下sqrt(17)关于998244353的二次剩余,把这个公式写成了O(1)公式,但是还是只能O(logn)解决,依旧不行,O(log)的原因就是快速幂还需要O(logn),如何消除这个log?受到BSGS的启发,我们先预处理掉一部分幂,存下来然后每次在数组里面找,这样预处理之后就是O(1)的方案。

(2)一阶分式递推。【一些常用的递推通项公式的求法】_特征方程_05      这种类型的叫做一阶分式递推。同理,我们做这个分式的特征方程:

                                                               【一些常用的递推通项公式的求法】_特征方程_06

这个方程也是二次方程,也会有两个根: x1,x2.所以简单推导一下:

首先是两个相异的根:

                                                       【一些常用的递推通项公式的求法】_递推_07

由于这里的x1,x2都是常数,所以两式相除可得:

                                                     【一些常用的递推通项公式的求法】_特征方程_08

OK,这里就显然等比数列了。

然后是两个相等的根:可以解出:x1=x2=   【一些常用的递推通项公式的求法】_特征方程_09.然后:

                                                     【一些常用的递推通项公式的求法】_递推_10.

把这个分式拆一下,然后x1带入可得:

                                                    【一些常用的递推通项公式的求法】_递推_11

显然等差数列。

例题:​​沈阳网赛G​​。题目的意思就是用n个三角形和n个bar连成电路,然后问你它的总电阻是多少。

其实这个题也是一个好题,奈何推出来的式子太特殊,题目要求的精度也不是很高,不需要公式即可解决。

思路:首先我们设bn表式已经连好了n个三角形和n个bar。来推n+1

                                       【一些常用的递推通项公式的求法】_特征方程_12

首先式bn和一个电阻为a的12并联,也就是:并联之后,再和23并联,这时和24串联,最后和34并联。按照电阻串并联的公式推一下,可以退出bn+1和bn的关系:

                                                           【一些常用的递推通项公式的求法】_递推公式_13

其实可以继续推下去把通项公式接出来,不过因为这个式子收敛的比较快,所以当n大于20左右时,就不会有精度的错误了,都按照20来做。所以没必要推公式,直接模拟就行。

#include<bits/stdc++.h>
double a;
double Solve(int n) {
if (n == 1) {
return 5.0 / 3.0 * a;
}
double b = Solve(n - 1);
double r = 3 * a + 1.0 / (1.0 / (3 * a) + 1.0 / a + 1.0 / b);
return 1.0 / (1 / (3.0 * a) + 1 / r);
}
const int N = 1e6 + 10;
char x[N];
int main() {
int T;
scanf("%d", &T);
while (T--)
{
scanf("%s", x);
int n;
if (strlen(x) > 1)n = 10;
else n = x[0] - '0';

scanf("%lf", &a);
printf("%.10f\n", Solve(n));
}
}

 


举报

相关推荐

0 条评论