Fibonacci 数列在 OI 中的应用

递推式 \(f_1=f_2=1,f_i=f_{i-1}+f_{i-2} \: (i \ge 3)\)
通项公式:

\[f_{n}={{1\over \sqrt{5}}[({1+\sqrt{5} \over 2})^n-({1-\sqrt{5} \over 2})^n]} \]

注意 \({1+\sqrt{5} \over 2} \cdot {1-\sqrt{5} \over 2}=-1\) ,因此列方程的话只要 \(x\)\(- {1 \over x}\)

通用维护方式:像维护复数一样维护一个数 \(x=a+b\sqrt{5}\),取模就对 \(a,b\) 分别取模即可。
由于最后结果一定是整数,所以 \([({(1+\sqrt{5}) \over 2})^n-({(1-\sqrt{5}) \over 2})^n]=0+b\sqrt{5}.\)

二次剩余:
若存在 \(5\)\(\bmod \: P\) 下的二次剩余,把 二次剩余 当 \(\sqrt{5}\) 用就可以了。

  • \(5\) 在  \(\bmod {10^9+9}\) 意义下有二次剩余为 \(383008016\)
  • \(5\) 在  \(\bmod {10^9+7}\) 意义下没有二次剩余。

找二次剩余的代码(暴力枚举即可,一般 \(P\)\(10^9\) 级别的都能 1 秒内出解)

	for(LL i=1;i<P;i++) 
		if(i*i%P==5) {
			cout<<i<<endl;
			return 0;
		}

性质 1:令 \(s_n=\sum_{i=1}^{n} f_i\)
有性质 \(s_n=f_{n+2}-f_2\)
证明:
数学归纳法。
\(k=1\)\(s_1=f_3-f_2=2-1=1\) 成立。
假设当 \(n=k\) 时成立,那 \(n+1\) 时。

\[\begin{aligned} s_{n+1}&=s_n+f_{n+1} \\ &=f_{n+2}-f_2+f_{n+1} \\ &=f_{n+3}-f_2 \\ &=f_{(n+1)+2}-f_2 \end{aligned} \]

性质 2: \(f_{n+m}=f_nf_{m-1}+f_{n+1}f_m=f_nf_{m+1}+f_{n+1}f_m-f_nf_m\)
用途

广义 Fibonacci 数列

\(F_1=b,F_2=a,F_i=F_{i-1}+F_{i-2} \: (i\ge 3)\)

性质 1 : 有 \(F_n=a \cdot f_{n-1}+b \cdot f_{n-2}.(n \ge 3)\)
证明:数学归纳法。

\(k=3\)\(F_3=F_2+F_1=a+b=a \cdot f_{2}+b \cdot f_{1}\) 成立。
假设当 \(n\le k\) 时成立,那 \(n+1\) 时。

\[\begin{aligned} F_{n+1}&=F_{n}+F_{n-1} \\ &=a \cdot f_{n-1}+b \cdot f_{n-2}+a \cdot f_{n-2}+b \cdot f_{n-3} \\ &=a \cdot (f_{n-1}+f_{n-2})+b \cdot (f_{n-2}+f_{n-3}) \\ &=a \cdot f_{n}+b \cdot f_{n-1} \\ &=a \cdot f_{(n+1)-1}+b \cdot f_{(n+1)-2} \end{aligned} \]

得证。

性质 2:与普通 Fibonacci 相同的前缀和性质 \(S_n=\sum_{i=1}^{n} F_i=F_{n+2}-F_2\)
证明:同上。

性质 3 :用 \(F[b,a]_i\) 表示 \(F_1=b,F_2=a\) 的广义 Fibonacci 数列。

\(F[b,a]_i+F[d,c]_i=F[b+d,a+c]_i\)

证明:数学归纳法。

有什么用

通项公式的用途就很广,因为可以把 Fibonacci 的求和转化为等比数列的求和。 比如:CF718C Sasha and Array

前缀和性质可以用来减小常数和码量,把 \(3\times 3\) 的矩阵变为 \(2\times 2\) ,因为不用额外维护一个前缀和。

\(F[b,a]_i+F[d,c]_i=F[b+d,a+c]_i\) 则可以用来配合数据结构 处理 区间加 Fibonacci 数列,区间求和的问题。
比如 CF446C DZY Loves Fibonacci Numbers

维护懒标记 \(lazytag=(b,a)\),表示 区间 \((l,r)\) 加上 \(F[a,b]\)

  • 对于一个完整的区间,加上的贡献即为 \(S[a,b]_{r-l+1}\).
  • 同时可以快速合并两个tag,\((b,a)+(c,d)=(b+c,a+d)\) 由性质 3.

其实 \(F[b,a]_i+F[d,c]_i=F[b+d,a+c]_i\) 也可以看成 矩阵的加法之类,维护 Fibonacci 数列通常维护 线段树+矩阵 也是可以的。

减小常数和复杂度的方法

同矩阵乘法。

可以预处理出 \(g[i]=C^{2^i},C\) 是转移矩阵,然后用向量去乘。
注意普通的快速幂是以 \(2\) 为底,可以取比较大的底,这样询问更快。
一般取 \(256\)\(65536\) 就可以看做是 \(O(1)\) 的了。

循环节

有引理 , Fibonacci 数列 在 \(\bmod P\) 意义下循环节 \(\le 6P\)

斐波那契数在模10,100,1000,1000……下的循环节大小分别为60,300,1500,15000,150000…….并且发现后来的循环节大小每次*10。

来自 Fibonacci Number
这个可以用同余的数尾数相同搞事情。

gcd

\[f[\gcd(n,m)]=\gcd(f[n],f[m]) \]

列方程

BZOJ5104 Fib 数列:求在 \(\bmod 10^9+9\) 的意义下,数字 \(z\) 在 Fib 数列中出现在哪个位置。

参考文章

posted @ 2022-07-05 15:33  cjlworld  阅读(69)  评论(0编辑  收藏  举报