借助模P数域,避免斐波那契通项公式浮点数运算

171 阅读1分钟

斐波那契数列

斐波那契数列:1,1,2,3,5,8,13,21,34,55,89...
斐波纳契数列以如下被以递归的方法定义:

Fn=Fn1+Fn2F_{n}^{} = F_{n-1}^{} + F_{n-2}^{}

这个数列从第三项开始,每一项都等于前两项之和。

这里我们直接给出通项公式:

Fn=15[(1+52)n+1(152)n+1]F_{n}^{}=\frac{1}{\sqrt{5} } \left [ \left(\frac{1+\sqrt{5}}{2} \right)_{}^{n+1} - \left(\frac{1-\sqrt{5}}{2} \right)_{}^{n+1} \right ]

具体求解方式可以看百度百科-斐波那契数列

使用通项公式的问题

  1. 涉及浮点数运算,不利于计算机处理
  2. 涉及 O(N)O(N) 复杂度的幂次运算

为处理浮点数问题,我们引入模P数域,将问题由实数运算转变为整数运算,转为整数运算后便可用快速幂算法在 O(logN)O(logN) 复杂度求解。

模P数域

定义运算

f(x)={x mod P, if xZa×b1 if x=abQZa+b×c if x=a+bc, a,bQ, cNa+b=f(a+b)a×b=f(a×b)a=r, if a+r=0a1=r, if a×r=1ab=a+(b)a÷b=a×b1a=r, if r×r=af(x) = \begin{cases} x\ mod \ P, & \text{ if } x\in Z \\ a\times b^{-1} & \text{ if } x=\frac{a}{b}\in Q\setminus Z \\ a+b\times \sqrt{c} & \text{ if } x=a+b\sqrt{c},\ a,b\in Q,\ c \in N \end{cases} \\ a+b = f(a+b) \\ a\times b = f(a\times b) \\ -a = r,\ if\ a+r=0 \\ a_{}^{-1} = r,\ if\ a\times r=1\\ a-b = a+(-b)\\ a{\div} b = a\times b^{-1}\\ \sqrt{a} = r,\ if\ r\times r=a

使用条件

  1. 原式结果为整数
  2. 原式结果小于P
  3. 没有多个不同值根式参与运算

在模P数域的通项公式

我们选择 P = 84906529, 于是

55=3589559315358955931=581230361+52(1+35895593)×21=17947797152(135895593)×21=66958733Fn=58123036×(17947797n+166958733n+1)\sqrt{5} \rightarrow \sqrt{5} = 35895593 \\ \frac{1}{\sqrt{5}} \rightarrow 35895593^{-1} = 58123036 \\ \frac{1+\sqrt{5}}{2} \rightarrow(1+35895593) \times 2^{-1} = 17947797 \\ \frac{1-\sqrt{5}}{2} \rightarrow(1-35895593) \times 2^{-1} = 66958733 \\ F_{n}^{}=58123036\times \left ( 17947797_{}^{n+1} -66958733_{}^{n+1} \right )

例子,取 n=10

F10=58123036×(17947797116695873311)=58123036×(6903646615870262)=58123036×53166204=89\begin{array}{l} F_{10}=58123036 \times\left(17947797^{11}-66958733^{11}\right) \\ =58123036 \times(69036466-15870262) \\ =58123036 \times 53166204 \\ =89 \end{array}

参考资料

【最讨厌做算法题的时候出现浮点数了,有什么方法可以避免?斐波那契数列和FFT均可适用!】 www.bilibili.com/video/BV1EM…