給定遞推式\(f_n =a_1f_{n-1} + a_2 f_{n-2}...+a_k f_{n-k}\)。函數
給定\(f_0,f_1...f_k\),求\(f_n\)。ui
先定義\(f_n\)的特徵方程:\(C(x) = x^{k} - a_1 x^{k-1} - a_2 x^{k-2}...-a_{k-1}x - a_k\)。spa
由基本代數定理,\(C(x) = 0\) 的解(稱爲特徵根)有\(K\)個,設爲\(\alpha_1\)、\(\alpha_2...\alpha_K\)。io
有\(f_n\)的母函數\(G(x) = \frac{P(x)}{(1-\alpha_1 x)(1-\alpha_2 x)...(1-\alpha_K x)}\)。class
對於非重根\(\alpha\),它在通項公式\(T_n\)中的貢獻形如\(A \alpha^n\),其中\(A\)爲待定係數。math
對於重根\(\beta\),設其爲\(r\)重根,它在通項公式中的貢獻形如\((\sum_{i=1}^r h_i n^{r-i} )\beta^n\)。
根據上述把通項式\(T_n\)列出來,利用前\(K\)項待定係數便可獲得通項公式。
定義向量\(A_i = (f_i,f_{i+1},f_{i+2}...f_{i+k-1})\),定義轉移矩陣\(M\)。
初始咱們知道\(A_0 = (f_0,f_1,f_2...f_{k-1})\),如今要求\(f_n\),即求\(A_n = (f_n,f_{n+1}...f_{n+k-1})\)。
能夠矩陣快速冪\(A_0*M^{n}\),複雜度\(O(k^3logn)\)。
將轉移矩陣\(M\)帶入特徵多項式有:\(F(M) = M^k - \sum_{i=1}^k a_i M^{k-i}\)。
根據某定理,咱們有\(F(M) = 0\),因此咱們能夠對\(M^n\)化簡,即\(M^n \equiv G(M)\ (mod\ F(M))\)。
即咱們求出\(G(M)\),那麼\(A_0G(M)\)與\(A_0M^n\)等價。
\(A_n = A_0G(M) = A_0\sum_{i=0}^{k-1} g_i M^i\),其中\(g_i\)即咱們多項式取模後第\(i\)項的係數。
而後\(A_n = \sum_{i=0}^{k-1} g_i A_0M^i\)。咱們只須要求\(f_n\),即只須要知道向量\(A\)的第一項。
因此\(A = A_0M^i\)的第一項是什麼?不就是\(f_i\)嗎!而\(f_i,i\in [0,k-1]\)咱們事先知道。
因此\(f_n = \sum_{i=0}^{k-1} g_i f_i\)。
實現上,關鍵在於求\(G(x)\),顯然\(M^n\)咱們不能一開始就把它存成一個多項式,因此須要倍增。
倍增的同時須要多項式乘法與多項式取模,
暴力作的話總複雜度爲\(O(k^2logn)\),使用多項式運算複雜度爲\(O(klogklogn)\)。