1. 程式人生 > >SPOJ FIBOSUM && FIBOSUM2

SPOJ FIBOSUM && FIBOSUM2

fibonacci $0 time 驗證 多項式 利用 left 循環節 mes

Fibonacci數列定義為

$$f_n = f_{n-1}+f_{n-2}, \text{以及初值}f_0=0, f_1=1.$$

本文之討論,皆在模$10^9+7$意義下。

FIBOSUM

給定$0 \le x \le y \le 10^9$,求$\sum_{i=x}^y f_i$。

解:

令$s_n = \sum_{i=1}^n f_i$,則

$$\begin{bmatrix} 1 & 1 & 0 \\ 0 & 1 & 1 \\ 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} s_{n-1} \\ f_n \\ f_{n-1} \end{bmatrix} = \begin{bmatrix} s_n \\ f_{n+1} \\ f_n \end{bmatrix}$$

於是$\sum_{i=x}^y f_i = s_y - s_{x-1}$,可用矩陣快速冪$O(\log x + \log y)$解決。

FIBOSUM2

給定$0 \le c < k \le 2^{15}$,以及$0 < n \le 10^{18}$,求

$$\sum_{i=1}^n f_{ki+c}.$$

解:

$$M = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}$$

$$M \begin{bmatrix} f_n \\ f_{n-1} \end{bmatrix} = \begin{bmatrix} f_{n+1} \\ f_n \end{bmatrix}$$

$$M^n = \begin{bmatrix} f_{n+1} & f_n \\ f_n & f_{n-1} \end{bmatrix}$$

於是$(M^n)_{01} = f_n$,

$$\left( \sum_{i=x}^y M^i \right)_{01} = \sum_{i=x}^y f_i$$

進而

$$ \left( \sum_{i=1}^n M^{ki+c} \right)_{01} = \sum_{i=1}^n f_{ki+c}$$

借此我們令

$$A = \begin{bmatrix} I & M^k \\ 0 & M^k \end{bmatrix}$$

可以驗證

$$A^n \begin{bmatrix} 0 \\ M^c \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^n M^{ki+c} \\ M^{kn+c} \end{bmatrix}$$

可以利用矩陣快速冪在$O(4^3 \log n)$求得。

這樣復雜度太高,我們繼續優化。

設$f(\lambda) = \det (\lambda I - A)$是矩陣$A$的特征多項式,即

$$f(\lambda) = \lambda^4 - a_1 \lambda^3 - a_2 \lambda^2 - a_3 \lambda - a_4. $$

其中$a_1 = f_{k+1}+f_{k-1}+2, a_2 = -(f_{k+1}f_{k-1}-f_k^2+2(f_{k+1}+f_{k-1})+1), a_3 = 2(f_{k+1}f_{k-1}-f_kf_k)+f_{k+1}+f_{k-1}, a_4 = f_k^2-f_{k+1}f_{k-1}.$

由Hamilton-Cayley定理,$f(A) = 0$,即

$$A^4 = a_1 A^3 + a_2 A^2 + a_3 A + a_4 I.$$

於是我們可以利用多項式乘法,把$A^n$化為$A$的三次多項式。

假設$A^n = c_3 A^3 + c_2 A^2 + c_1 A^1 + c_4$,並令$s_n = \sum_{i=1}^n f_{ki+c}$,有

$$s_n = \sum_{i=0}^3 c_is_i = c_1s_1+c_2s_2+c_3s_3$$

時間復雜度$O(4^2 \log n)$。

我們仍可繼續優化,考慮到Fibonacci數列在模$10^9+7$下的循環節是$2 \times 10^9+16$,並且

$$s_n = \sum_{i=1}^{2 \times 10^9+16} f_{ki+c} \equiv \sum_{i=1}^{2 \times 10^9+16} f_{i} \equiv 0 \pmod {10^9+7}.$$

於是

$$s_n \equiv s_{n \bmod (2 \times 10^9+16)}.$$

則可以把$n$限制到 int 範圍內。

SPOJ FIBOSUM && FIBOSUM2