线性递推求值问题

常系数线性递推关系的定义

对于满足
a n = ∑ i = 1 k c i a n − i + f ( n ) a_n=\sum_{i=1}^{k}c_ia_{n-i}+f(n) an=i=1kciani+f(n)
一类的递推关系(其中 c , k c,k c,k 为常数),我们称之为常系数线性递推关系。

只要给定 a 0 , a 1 , … , a k − 1 a_0,a_1,\dots,a_{k-1} a0,a1,,ak1 以及 c 1 , c 2 , … , c k c_1,c_2,\dots,c_k c1,c2,,ck 以及 f ( n ) f(n) f(n) ,我们就能求出 a a a 的任意一项。

这个问题的一般形式是不能快速求解的,比如令 f ( n ) = ln ⁡ n f(n)=\ln n f(n)=lnn 。但有一些特殊形式我们可以快速求解。我们先从齐次常系数线性递推关系来研究。

齐次常系数线性递推关系的求值

齐次常系数线性递推关系即 f ( n ) = 0 f(n)=0 f(n)=0 的情况,此时 a n = ∑ i = 1 k c i a n − i a_n=\sum_{i=1}^{k}c_ia_{n-i} an=i=1kciani

这看起来像线性变换,因此考虑从线性变换的角度解决这个问题。

矩阵优化

我们构造初始向量

x ⃗ = [ a k − 1 a k − 2 ⋮ a 1 a 0 ] \vec x= \left[ \begin{matrix} a_{k-1} \\ a_{k-2} \\ \vdots \\ a_1 \\ a_0 \\ \end{matrix} \right] x =ak1ak2a1a0

以及转移矩阵

A = [ c 1 c 2 ⋯ c k − 2 c k − 1 c k 1 0 ⋯ 0 0 0 0 1 ⋯ 0 0 0 ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 ⋯ 1 0 0 0 0 ⋯ 0 1 0 ] A= \left[ \begin{matrix} c_1 &c_2 &\cdots &c_{k-2} &c_{k-1} & c_k\\ 1 & 0 &\cdots & 0 & 0 & 0 \\ 0 & 1 &\cdots & 0 & 0 & 0 \\ \vdots &\vdots & \ddots &\vdots &\vdots &\vdots \\ 0 & 0 &\cdots & 1 & 0 & 0 \\ 0 & 0 &\cdots & 0 & 1 & 0 \\ \end{matrix} \right] A=c11000c20100ck20010ck10001ck0000

于是

A n ⋅ x ⃗ = [ a n + k − 1 a n + k − 2 ⋮ a n + 1 a n ] A^n\cdot \vec x= \left[ \begin{matrix} a_{n+k-1}\\ a_{n+k-2} \\ \vdots \\ a_{n+1}\\ a_n\\ \end{matrix} \right] Anx =an+k1an+k2an+1an

这样我们就可以用矩阵快速幂来求 a n a_n an 了,复杂度 O ( k 3 log ⁡ n ) O(k^3\log n) O(k3logn)

但这个复杂度依然不够优秀,考虑从线性代数的角度切入。

特征多项式优化

事实上,我们可以把 A n A^n An 表示为 A 0 , A 1 , ⋯   , A k − 1 A^0,A^1,\cdots,A^{k-1} A0,A1,,Ak1 的线性组合,并且我们有:

A n = ∑ i = 1 k c i A n − i A^{n}=\sum_{i=1}^{k} c_iA^{n-i} An=i=1kciAni

为什么呢?
我们可以从 C a y l a y − C a m i l t o n Caylay-Camilton CaylayCamilton 定理1来考虑:

对于矩阵 A A A 的特征多项式 f ( λ ) = det ⁡ ∣ λ I − A ∣ f( \lambda )=\det \left| \lambda I-A\right| f(λ)=detλIA ,我们有 f ( A ) = 0 f(A)=0 f(A)=0

而对于上述转移矩阵,我们有:

f ( λ ) = λ k − ∑ i = 1 k c i λ n − i f(\lambda)=\lambda ^k-\sum_{i=1}^{k}c_i \lambda ^{n-i} f(λ)=λki=1kciλni

A A A 代入上式即可。

当然我们也可以从其他角度考虑。

A n ⋅ x ⃗ = [ a n + k − 1 a n + k − 2 ⋮ a n + 1 a n ] A^{n}\cdot \vec x= \begin{bmatrix} a_{n+k-1}\\ a_{n+k-2} \\ \vdots \\ a_{n+1}\\ a_n\\ \end{bmatrix} Anx =an+k1an+k2an+1an

∑ i = 1 k c i A n − i ⋅ x ⃗ = [ ∑ i = 1 k c i a n − i + k − 1 ∑ i = 1 k c i a n − i + k − 2 ⋮ ∑ i = 1 k c i a n − i + 1 ∑ i = 1 k c i a n − i ] = [ a n + k − 1 a n + k − 2 ⋮ a n + 1 a n ] = A n ⋅ x ⃗ \sum_{i=1}^{k} c_iA^{n-i}\cdot \vec x= \begin{bmatrix} \sum_{i=1}^kc_ia_{n-i+k-1}\\\\ \sum_{i=1}^kc_ia_{n-i+k-2}\\\\ \vdots \\\\ \sum_{i=1}^kc_ia_{n-i+1}\\\\ \sum_{i=1}^kc_ia_{n-i}\\\\ \end{bmatrix}= \begin{bmatrix} a_{n+k-1}\\\\ a_{n+k-2} \\\\ \vdots \\\\ a_{n+1}\\\\ a_n\\\\ \end{bmatrix}= A^{n}\cdot \vec x i=1kciAnix =i=1kciani+k1i=1kciani+k2i=1kciani+1i=1kciani=an+k1an+k2an+1an=Anx

也即:

( A n − ∑ i = 1 k c i A n − i ) ⋅ x ⃗ = 0 (A^{n}-\sum_{i=1}^{k} c_iA^{n-i})\cdot \vec x=0 (Ani=1kciAni)x =0

由于任意向量 x ⃗ \vec x x 都满足这个关系,因此我们就得到了 A n − ∑ i = 1 k c i A n − i = 0 A^{n}-\sum_{i=1}^{k} c_iA^{n-i}=0 Ani=1kciAni=0

n = k n=k n=k 就有 f ( A ) = 0 f(A)=0 f(A)=0

无论如何,有了上述关系,我们只要求出 λ n   m o d   f ( λ ) \lambda ^n \bmod f(\lambda) λnmodf(λ) 即可。

g ( λ ) = λ n   m o d   f ( λ ) g(\lambda) =\lambda^n \bmod f(\lambda) g(λ)=λnmodf(λ) ,则 A n = f ( A ) P ( A ) + g ( A ) = 0 ⋅ P ( A ) + g ( A ) = g ( A ) A^n=f(A)P(A)+g(A)=0\cdot P(A)+g(A)=g(A) An=f(A)P(A)+g(A)=0P(A)+g(A)=g(A)

再设

g ( λ ) = ∑ i = 0 k − 1 h i λ i g(\lambda)=\sum_{i=0}^{k-1}h_i\lambda^i g(λ)=i=0k1hiλi

A n ⋅ x ⃗ = g ( A ) ⋅ x ⃗ = ∑ i = 0 k − 1 h i A i ⋅ x ⃗ = [ ∑ i = 0 k − 1 h i a k − 1 + i ∑ i = 0 k − 1 h i a k − 2 + i ⋮ ∑ i = 0 k − 1 h i a 1 + i ∑ i = 0 k − 1 h i a i ] A^n\cdot \vec x= g(A)\cdot \vec x= \sum_{i=0}^{k-1}h_iA^i \cdot \vec x= \begin{bmatrix} \sum_{i=0}^{k-1}h_ia_{k-1+i}\\ \\ \sum_{i=0}^{k-1}h_ia_{k-2+i}\\ \\ \vdots \\ \\ \sum_{i=0}^{k-1}h_ia_{1+i}\\ \\ \sum_{i=0}^{k-1}h_ia_{i}\\ \\ \end{bmatrix} Anx =g(A)x =i=0k1hiAix =i=0k1hiak1+ii=0k1hiak2+ii=0k1hia1+ii=0k1hiai

这实际上是一个卷积的形式。我们只要把 h h h a a a 的前 l + k − 1 l+k-1 l+k1 项做多项式乘法就能求出连续的 l l l 项,如果只要求出单项就只需计算 ∑ i = 0 k − 1 h i a i \sum_{i=0}^{k-1}h_ia_i i=0k1hiai

g ( λ ) g(\lambda) g(λ) 我们可以用倍增+多项式取模的方式。

如果使用 F F T FFT FFT 那么总复杂度就是 O ( k log ⁡ k log ⁡ n ) O(k\log k\log n) O(klogklogn) ,暴力取模就是 O ( k 2 log ⁡ n ) O(k^2\log n) O(k2logn)

以及还有一个问题:怎么求出 a a a 的前 l l l 项?暴力求是 O ( k l ) O(kl) O(kl) 的。

由于这是一个序列问题,要求的项数不多,我们考虑用生成函数法解决。

f ( x ) = ∑ i = 0 ∞ a i x i , C ( x ) = ∑ i = 1 k c i x i f(x)=\sum_{i=0}^{\infty}a_ix^i,C(x)=\sum_{i=1}^kc_ix^i f(x)=i=0aixi,C(x)=i=1kcixi

由于将 f , C f,C f,C 卷积在前 k k k 项是错误的,因此我们构造

g ( x ) = f ( x ) − f ( x ) C ( x ) ( m o d x k ) g(x)=f(x)-f(x)C(x) \pmod{x^k} g(x)=f(x)f(x)C(x)(modxk)

于是我们有 f ( x ) = f ( x ) C ( x ) + g ( x ) f(x)=f(x)C(x)+g(x) f(x)=f(x)C(x)+g(x)

因此 f ( x ) = g ( x ) 1 − C ( x ) f(x)=\frac{g(x)} {1-C(x)} f(x)=1C(x)g(x)

值得一提的是 1 − C ( x ) 1-C(x) 1C(x) 和转移矩阵特征多项式的关系。以及逆推这个过程我们会发现:若序列 a a a 的生成函数满足 f ( x ) = g ( x ) 1 − C ( x ) f(x)=\frac{g(x)} {1-C(x)} f(x)=1C(x)g(x) deg ⁡ g &lt; deg ⁡ C = k \deg g&lt;\deg C=k degg<degC=k C C C 的常数项为 0 0 0 (实际上不为 1 1 1 即可),我们就可以把该序列与一个 k k k 阶线性递推方程相对应,这一点对非齐次线性递推也同样适用。

于是我们就能在 O ( k log ⁡ k log ⁡ n ) O(k\log k\log n) O(klogklogn) 的时间内解决齐次常系数线性递推的求值问题了。

一类特殊非齐次常系数线性递推关系的求值

注:以下部分的一些多项式算法,在我的这一篇博文中均有给出解法。

我们现在已经掌握齐次线性递推关系的求值算法了。

现在来讨论 f ( n ) f(n) f(n) 为多项式函数的情况。

我们尝试用化归法转化为齐次线性线性递推关系求解。

我们知道:
a n = ∑ i = 1 k c i a n − i + f ( n ) a_n=\sum_{i=1}^{k}c_ia_{n-i}+f(n) an=i=1kciani+f(n)
a n − 1 = ∑ i = 1 k c i a n − 1 − i + f ( n − 1 ) a_{n-1}=\sum_{i=1}^{k}c_ia_{n-1-i}+f(n-1) an1=i=1kcian1i+f(n1)
a n − a n − 1 = ∑ i = 1 k c i a n − i − ∑ i = 1 k c i a n − 1 − i + f ( n ) − f ( n − 1 ) = ∑ i = 1 k c i a n − i − ∑ i = 1 k c i a n − 1 − i + f 1 ( n ) a_n-a_{n-1}=\sum_{i=1}^{k}c_ia_{n-i}-\sum_{i=1}^{k}c_ia_{n-1-i}+f(n)-f(n-1)=\sum_{i=1}^{k}c_ia_{n-i}-\sum_{i=1}^{k}c_ia_{n-1-i}+f_1(n) anan1=i=1kcianii=1kcian1i+f(n)f(n1)=i=1kcianii=1kcian1i+f1(n)

显然 deg ⁡ f 1 = deg ⁡ f − 1 \deg f_1=\deg f-1 degf1=degf1 ,设 f f f 的次数为 m m m ,我们只需要对其进行 m + 1 m+1 m+1 次对减就能转化为齐次关系。
现在问题在于如何求出新的递推关系以及 a k , ⋯ &ThinSpace; , a m + k a_k,\cdots,a_{m+k} ak,,am+k

a k , ⋯ &ThinSpace; , a m + k a_k,\cdots,a_{m+k} ak,,am+k 的值我们可以仿照上面的生成函数法:

F ( x ) = ∑ i = 0 ∞ a i x i , C ( x ) = ∑ i = 1 k c i x i , G ( x ) = F ( x ) − F ( x ) C ( x ) ( m o d x k ) , H ( x ) = ∑ i = k ∞ f ( i ) x i F(x)=\sum_{i=0}^{\infty}a_ix^i,C(x)=\sum_{i=1}^kc_ix^i,G(x)=F(x)-F(x)C(x) \pmod{x^k},H(x)=\sum_{i=k}^{\infty} f(i)x^i F(x)=i=0aixi,C(x)=i=1kcixi,G(x)=F(x)F(x)C(x)(modxk),H(x)=i=kf(i)xi

F ( x ) = F ( x ) C ( x ) + G ( x ) + H ( x ) , F ( x ) = G ( x ) + H ( x ) 1 − C ( x ) F(x)=F(x)C(x)+G(x)+H(x),F(x)=\frac{G(x)+H(x)} {1-C(x)} F(x)=F(x)C(x)+G(x)+H(x),F(x)=1C(x)G(x)+H(x)

不过这样我们需要使用一次多点求值算法,复杂度 O ( m log ⁡ 2 m ) O(m\log^2 m) O(mlog2m)

至于新的递推关系,由于对减的特点,设原递推关系的转移矩阵特征多项式为 f ( λ ) f(\lambda) f(λ) ,新的递推关系的转移矩阵的特征多项式就是 f ( λ ) ( x − 1 ) m + 1 f(\lambda)(x-1)^{m+1} f(λ)(x1)m+1 ,这样就得到了新的递推关系式。

于是求解该问题的总复杂度为 O ( m log ⁡ 2 m + ( m + k ) log ⁡ ( m + k ) log ⁡ n ) O(m\log^2 m+(m+k)\log (m+k)\log n) O(mlog2m+(m+k)log(m+k)logn)

对该问题的进一步优化

实际上除了求 a 0 , a 1 , ⋯ &ThinSpace; , a m + k a_0,a_1,\cdots,a_{m+k} a0,a1,,am+k 的值以外,我们仅需要求得 x n &VeryThinSpace; m o d &VeryThinSpace; f ( x ) ( x − 1 ) m + 1 x^n \bmod f(x)(x-1)^{m+1} xnmodf(x)(x1)m+1

f ( x ) f(x) f(x) ( x − 1 ) m + 1 (x-1)^{m+1} (x1)m+1 互质,我们可以求出 x n &VeryThinSpace; m o d &VeryThinSpace; f ( x ) x^n \bmod f(x) xnmodf(x) ,再求出 x n &VeryThinSpace; m o d &VeryThinSpace; ( x − 1 ) m + 1 x^n \bmod (x-1)^{m+1} xnmod(x1)m+1 ,最后使用中国剩余定理合并。不互质的话我们只需提取出 f ( x ) f(x) f(x) 中的 ( x − 1 ) (x-1) (x1) 因式即可。

对于 x n &VeryThinSpace; m o d &VeryThinSpace; ( x − 1 ) m + 1 x^n \bmod (x-1)^{m+1} xnmod(x1)m+1 ,如果我们使用倍增取模,那么复杂度就是 O ( m log ⁡ m log ⁡ n + k log ⁡ k log ⁡ n ) O(m\log m\log n+k\log k\log n) O(mlogmlogn+klogklogn) ,并没有真正的优化复杂度。

但显然由于所模函数的特殊性,我们可以快速取模。我们只要求出 f ( x + 1 ) &VeryThinSpace; m o d &VeryThinSpace; x m + 1 f(x+1) \bmod x^{m+1} f(x+1)modxm+1 ,再代入 ( x − 1 ) (x-1) (x1) 就能求出 f ( x ) &VeryThinSpace; m o d &VeryThinSpace; ( x − 1 ) m + 1 f(x) \bmod (x-1)^{m+1} f(x)mod(x1)m+1

由于被取模函数的特殊性甚至可以不需要用到多项式算法,而直接使用组合数学的方法 O ( m ) O(m) O(m) 算出。当然这不是重点。

根据中国剩余定理我们需要求解这样的方程:
f ( x ) P ( x ) + ( x − 1 ) m + 1 Q ( x ) = 1 f(x)P(x)+(x-1)^{m+1}Q(x)=1 f(x)P(x)+(x1)m+1Q(x)=1

我们可以直接套用 e x g c d exgcd exgcd 算法,复杂度是 O ( ( m + k ) log ⁡ ( m + k ) ) O((m+k)\log (m+k)) O((m+k)log(m+k)) ,但常数较大。

一个较好的做法是转化为 f ( x + 1 ) P ( x + 1 ) + x m + 1 Q ( x + 1 ) = 1 f(x+1)P(x+1)+x^{m+1}Q(x+1)=1 f(x+1)P(x+1)+xm+1Q(x+1)=1 。这样就是多项式求逆了。

F ( x + q ) F(x+q) F(x+q) 是一个经典的问题,可见于上文提到的另一篇博文。

求出 P ( x ) P(x) P(x) 之后,设 A ( x ) = x n &VeryThinSpace; m o d &VeryThinSpace; f ( x ) , B ( x ) = x n &VeryThinSpace; m o d &VeryThinSpace; ( x − 1 ) m + 1 A(x)= x^n \bmod f(x),B(x)=x^n \bmod (x-1)^{m+1} A(x)=xnmodf(x),B(x)=xnmod(x1)m+1 ,那么就有:

x n ≡ A ( x ) ( x − 1 ) m + 1 Q ( x ) + B ( x ) f ( x ) P ( x ) ≡ A ( x ) ( 1 − f ( x ) P ( x ) ) + B ( x ) f ( x ) P ( x ) ( m o d f ( x ) ( x − 1 ) m + 1 ) x^n \equiv A(x)(x-1)^{m+1}Q(x)+B(x)f(x)P(x) \equiv A(x)(1-f(x)P(x))+B(x)f(x)P(x) \pmod {f(x)(x-1)^{m+1}} xnA(x)(x1)m+1Q(x)+B(x)f(x)P(x)A(x)(1f(x)P(x))+B(x)f(x)P(x)(modf(x)(x1)m+1)

这样求解的总复杂度是 O ( m log ⁡ 2 m + k log ⁡ k log ⁡ n ) O(m\log ^2 m+k\log k \log n) O(mlog2m+klogklogn)

更一般的形式

对于

f ( n ) = ∑ i = 1 t F i ( n ) q i n f(n)=\sum_{i=1}^t F_i(n)q_i^n f(n)=i=1tFi(n)qin

其中 F i ( n ) F_i(n) Fi(n) 为多项式函数, q i q_i qi 两两不相等。

我们依然可以仿照上面的方式进行求值。

每次设新的数列 b n = a n q i n b_n=\frac {a_n} {q_i^n} bn=qinan 并逐次差分即可。

F i F_i Fi 的次数为 m i m_i mi ,总差分次数为 M = ∑ i = 1 t ( m i + 1 ) M=\sum\limits_{i=1}^t (m_i+1) M=i=1t(mi+1) ,由于每次消去一个多项式时其余多项式的次数并不会发生变化,因此我们最终会将其化为齐次的 k + M k+M k+M 阶方程。

考虑如何求解新递推关系的特征方程。

设我们上一次消去的函数为第 l l l 项即 F l ( n ) q l n F_l(n)q_l^n Fl(n)qln ,则新的序列 b n b_n bn 满足 b n = a n q l n b_n=\frac{a_n} {q_l^n} bn=qlnan

b n b_n bn 的递推方程的特征多项式:
( x k − ∑ i = 1 k c i q l i x n − i ) ∏ i = 1 l ( x − q i q l ) m i + 1 (x^k-\sum_{i=1}^{k}\frac{c_i}{q_l^i}x^{n-i})\prod_{i=1}^l(x-\frac{q_i} {q_l})^{m_i+1} (xki=1kqlicixni)i=1l(xqlqi)mi+1

而此时的函数形式为

f ′ ( n ) = ∑ i = l + 1 t F i ′ ( n ) ( q i q l ) n f&#x27;(n)=\sum_{i=l+1}^t F_i&#x27;(n)(\frac{q_i} {q_l})^n f(n)=i=l+1tFi(n)(qlqi)n

且各多项式函数的次数不变。

这并不难推导出来。当我们需要消去 F l + 1 ′ F&#x27;_{l+1} Fl+1 时,新的序列为 b ′ ( n ) = b n q l + 1 n q l n = b n q l n q l + 1 = a n q l + 1 n b&#x27;(n)=\frac{b_n} {\frac{q_{l+1}^n}{q_l^n}}=b_n\frac{q_l^n} {q^{l+1}}=\frac{a_n} {q_{l+1}^n} b(n)=qlnql+1nbn=bnql+1qln=ql+1nan ,则特征方程中每一个因式从高到低各项分别乘上 ( q l q l + 1 ) j (\frac{q_l} {q_{l+1}})^j (ql+1ql)j ,且所有 F i ′ ( n ) ( q i q l ) n F&#x27;_i(n)(\frac{q_i} {q_l})^n Fi(n)(qlqi)n 乘上 q l n q l + 1 \frac{q_l^n} {q^{l+1}} ql+1qln ,变为 F i ′ ( n ) ( q i q l + 1 ) n F&#x27;_i(n)(\frac{q_i} {q_{l+1}})^n Fi(n)(ql+1qi)n

此时 F l + 1 ′ F&#x27;_{l+1} Fl+1 的指数为 1 1 1 ,其余函数指数不为 1 1 1 ,差分 m l + 1 + 1 m_{l+1}+1 ml+1+1 次会导致特征多项式乘上 ( x − 1 ) m l + 1 + 1 (x-1)^{m_{l+1}+1} (x1)ml+1+1 并消去 F l + 1 ′ F&#x27;_{l+1} Fl+1,且其余函数的多项式次数不变。

归纳证明即可。

通过这个结论,我们可以推导出 a n a_n an 最终化为齐次递推方程后方程的特征多项式为

( x k − ∑ i = 1 k c i x n − i ) ∏ i = 1 t ( x − q i ) m i + 1 (x^k-\sum_{i=1}^{k}c_ix^{n-i})\prod_{i=1}^t(x-q_i)^{m_i+1} (xki=1kcixni)i=1t(xqi)mi+1

我们依然可以用原来的方法计算 x n &VeryThinSpace; m o d &VeryThinSpace; ( x − q i ) m i + 1 x^n \bmod (x-q_i)^{m_i+1} xnmod(xqi)mi+1 ,并用类似解同余方程的方法以及 e x g c d exgcd exgcd 算法合并,注意要使用分治合并的方法,最坏情况下复杂度为 O ( M log ⁡ M log ⁡ t ) O(M \log M\log t) O(MlogMlogt)

同时我们要求出 a a a O ( k + M ) O(k+M) O(k+M) 项。使用生成函数法我们还是要求出每个函数的点值,单次求点值的复杂度为 O ( min ⁡ { m i log ⁡ 2 m i + M log ⁡ m i , m i M } ) O( \min\{m_i\log^2 m_i+M\log m_i,m_iM\}) O(min{milog2mi+Mlogmi,miM}) ,(注意多项式求值也可以当做线性递推问题求连续点的点值),并且我们需要求 t t t 次。当 t t t 较小时复杂度是 O ( t M log ⁡ M + M log ⁡ 2 M ) O(tM\log M+M\log^2 M) O(tMlogM+Mlog2M) 的, t t t 较大时使用暴力求值法更优秀,复杂度为 O ( M 2 ) O(M^2) O(M2)

总复杂度 O ( min ⁡ { t M log ⁡ M + M log ⁡ 2 M , M 2 } + k log ⁡ k log ⁡ n ) O(\min\{tM\log M+M\log^2 M,M^2\}+k\log k \log n) O(min{tMlogM+Mlog2M,M2}+klogklogn)

对一般形式更进一步的优化

在上述算法中,最劣情况下复杂度含有一个 M 2 M^2 M2 ,显然是非常不优秀的。

考虑什么地方出现了问题。

显然瓶颈在于如何求 a k , a k + 1 , ⋯ &ThinSpace; , a k + M a_k,a_{k+1},\cdots,a_{k+M} ak,ak+1,,ak+M ,而当 t t t 很大时也就是底数不同的指数函数过多时暴力求出点值用以表示序列的生成函数是不优秀的。

类似于序列 1 n + 2 n + ⋯ + m n 1^n+2^n+\cdots +m^n 1n+2n++mn 的生成函数为 ∑ i = 1 m 1 1 − i x \sum\limits_{i=1}^{m}\frac{1}{1-ix} i=1m1ix1 ,显然可以使用分治 F F T FFT FFT O ( m log ⁡ 2 m ) O(m\log^2 m) O(mlog2m) 时间内求出,但是若是使用上面的点值法表示生成函数复杂度就会达到 m 2 m^2 m2

现在我们考虑如何快速求出序列的通项形如 a n = F ( n ) q n a_n=F(n)q^n an=F(n)qn 的生成函数。

首先我们依然可以设 b n = a n q n b_n=\frac{a_n} {q^n} bn=qnan 将该问题化归为求解 F ( n ) F(n) F(n) 的生成函数。

多项式生成函数问题在上文提到的博文中有给出解法,这里不再赘述。

对于线性递推式:

a n = ∑ i = 1 k c i a n − i + f ( n ) a_{n}=\sum_{i=1}^{k} c_ia_{n-i}+f(n) an=i=1kciani+f(n)

f ( n ) = ∑ i = 1 t F i ( n ) q i n f(n)=\sum_{i=1}^t F_i(n)q_i^n f(n)=i=1tFi(n)qin

我们只需设 H ( x ) = ∑ i = k ∞ f ( i ) x i = x k ∑ i = 1 t G i ( x ) ( 1 − q i x ) m i + 1 H(x)=\sum_{i=k}^{\infty} f(i)x^i=x^k\sum_{i=1}^{t} \frac{G_i(x)} {(1-q_ix)^{m_i+1}} H(x)=i=kf(i)xi=xki=1t(1qix)mi+1Gi(x)
即可。

只需 O ( ∑ i = 1 t m i log ⁡ 2 m i ) O(\sum\limits_{i=1}^{t}m_i\log^2 m_i) O(i=1tmilog2mi) 求出每一个 G i G_i Gi

然后使用与上面使用生成函数法时一致的做法,即:

F ( x ) = G ( x ) + H ( x ) 1 − C ( x ) F(x)=\frac{G(x)+H(x)} {1-C(x)} F(x)=1C(x)G(x)+H(x)

就可以求出 a k , a k + 1 , ⋯ &ThinSpace; , a M + k a_k,a_{k+1},\cdots,a_{M+k} ak,ak+1,,aM+k 的值了。

类似的,依然有总复杂度为 O ( M log ⁡ 2 M + k log ⁡ k log ⁡ n ) O(M\log^2 M+k\log k\log n) O(Mlog2M+klogklogn)


  1. C a y l a y − C a m i l t o n Caylay-Camilton CaylayCamilton 定理可以从线性代数的相关资料以及网络上找到证明。 ↩︎

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划是一种常用的解决问题的算法,其核心思想是将一个复杂的问题分解为多个子问题进行求解,通过保存之前的状态来减少计算量,从而达到优化算法的目的。动态规划有两种求解方式,一种是递推求解法,另一种是记忆化搜索法。 递推求解法是指从小到大依次计算子问题的解,逐步推导出整个问题的最优解。这种方法需要定义一个状态转移方程,通过状态转移方程来求解问题。具体步骤如下: 1. 定义状态:将原问题拆分成若干个子问题,根据子问题定义状态。 2. 定义状态转移方程:根据子问题之间的关系,定义状态转移方程。 3. 确定边界条件:确定最小的子问题的解。 4. 递推求解:根据状态转移方程从边界条件出发,逐步计算得到整个问题的解。 下面以斐波那契数列为例,介绍动态规划递推求解法的具体实现过程。 假设要求斐波那契数列的第n项的值,斐波那契数列的定义如下: f(0) = 0 f(1) = 1 f(n) = f(n-1) + f(n-2) (n>=2) 1. 定义状态 将原问题拆分成若干个子问题,根据子问题定义状态。对于斐波那契数列,我们可以将其拆分成n-1和n-2两个子问题,然后定义状态f(n)表示斐波那契数列的第n项的值。 2. 定义状态转移方程 根据子问题之间的关系,定义状态转移方程。对于斐波那契数列,由于f(n)依赖于f(n-1)和f(n-2),因此可以得到状态转移方程: f(n) = f(n-1) + f(n-2) 3. 确定边界条件 确定最小的子问题的解。对于斐波那契数列,边界条件为f(0)=0和f(1)=1。 4. 递推求解 根据状态转移方程从边界条件出发,逐步计算得到整个问题的解。具体实现过程如下: ```python def fibonacci(n): if n == 0: return 0 elif n == 1: return 1 else: f = * (n+1) f = 0 f = 1 for i in range(2, n+1): f[i] = f[i-1] + f[i-2] return f[n] ``` 以上就是动态规划递推求解法的具体实现过程。如果您有任何疑问或者其他相关问题,请随时提出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值