文章目录
一、引例
【例题一】 f ( 0 ) = 0 , f ( 1 ) = 1 , f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(0) = 0, f(1) = 1, f(n) = f(n − 1) + f(n − 2) f(0)=0,f(1)=1,f(n)=f(n−1)+f(n−2) 其中 ( n ≥ 2 ) (n ≥ 2) (n≥2),求 f ( n ) m o d M ( M < = 1 0 9 ) f(n) \mod M (M<=10^9) f(n)modM(M<=109);
- 这个数列就是经典的斐波那契数列,读者可以先想一下,如何在时间允许的情况下计算出 f ( n ) f(n) f(n) 的值;
- 这节内容非常有意思,由于涉及到一个线性代数里面的结构,它的名字叫 矩阵,如果对大学的内容已经忘得一干二净的话,我们先来复习一些概念,为了避免过程枯燥乏味,所有定义相关的内容,我都会一笔带过,争取尽快达到读者想要观看的内容;
二、矩阵乘法
- 矩阵 A x × y A_{x \times y} Ax×y 和 矩阵 B u × v B_{u \times v} Bu×v 相乘的前提条件是 y = = u y==u y==u ,并且相乘后得到的矩阵为 C x × v C_{x \times v} Cx×v(即 A A A 的行和 B B B 的列构成了矩阵 C C C 的行列);
- 例如
2
×
3
2 \times 3
2×3 的矩阵
A
2
×
3
A_{2 \times 3}
A2×3 和
3
×
4
3 \times 4
3×4 的矩阵
B
3
×
2
B_{3 \times 2}
B3×2 相乘后得到一个
2
×
2
2 \times 2
2×2 的矩阵
C
2
×
2
C_{2 \times 2}
C2×2 (用
A
A
A 的每一行去乘上
B
B
B 的每一列);
A 2 × 3 = [ a 11 a 12 a 13 a 21 a 22 a 23 ] B 3 × 2 = [ b 11 b 12 b 21 b 22 b 31 b 32 ] A_{2 \times 3} = \left[ \begin{matrix} a_{11} & a_{12} & a_{13}\\ a_{21} & a_{22} & a_{23} \end{matrix} \right] \quad B_{3 \times 2} = \left[ \begin{matrix} b_{11} & b_{12}\\ b_{21} & b_{22}\\ b_{31} & b_{32} \end{matrix} \right] A2×3=[a11a21a12a22a13a23]B3×2= b11b21b31b12b22b32
C 2 × 2 = [ a 11 b 11 + a 12 b 21 + a 13 b 31 a 11 b 12 + a 12 b 22 + a 13 b 32 a 21 b 11 + a 22 b 21 + a 23 b 31 a 21 b 12 + a 22 b 22 + a 23 b 32 ] C_{2 \times 2} = \left[ \begin{matrix} a_{11}b_{11} + a_{12}b_{21} + a_{13}b_{31} & a_{11}b_{12} + a_{12}b_{22} + a_{13}b_{32} \\ a_{21}b_{11} + a_{22}b_{21} + a_{23}b_{31} & a_{21}b_{12} + a_{22}b_{22} + a_{23}b_{32} \\ \end{matrix} \right] \quad C2×2=[a11b11+a12b21+a13b31a21b11+a22b21+a23b31a11b12+a12b22+a13b32a21b12+a22b22+a23b32]
- 了解更多矩阵乘法相关内容,参见:矩阵乘法加速
三、矩阵的幂
1、方阵
- 行数 和 列数 相同的矩阵被称为方阵;
- A m × m A_{m \times m} Am×m 被称为 m m m 阶方阵;
- 两个方阵相乘的时间复杂度为 O ( m 3 ) O(m^3) O(m3);
2、矩阵的幂运算
- 只有方阵才能进行幂运算,矩阵幂运算的定义为连续 n n n 个矩阵 A A A 连乘,表示为 A n A^n An;
- 矩阵连乘满足递推公式(其中
I
I
I 为单位矩阵 ):
A n { I n = 0 A n − 1 × A n > 0 A^n\begin{cases} I & n=0\\ A^{n-1} \times A & n>0 \end{cases} An{IAn−1×An=0n>0 - 若矩阵 A A A 为 m m m 阶 方阵,那么这个算法的时间复杂度就是 O ( n m 3 ) O(nm^3) O(nm3);
四、矩阵快速幂
【例题二】 给定一个
m
(
m
<
=
50
)
m (m<=50)
m(m<=50) 阶矩阵,求它的
n
(
n
<
=
1
0
9
)
n (n<=10^9)
n(n<=109) 次幂的对角线和
m
o
d
1000007
\mod 1000007
mod1000007 的值;
A
n
=
[
a
11
a
12
⋯
a
1
m
a
21
a
22
⋯
a
2
m
⋮
⋮
⋱
⋮
a
m
1
a
m
2
⋯
a
m
m
]
n
A^n=\begin{bmatrix} {a_{11}}&{a_{12}}&{\cdots}&{a_{1m}}\\ {a_{21}}&{a_{22}}&{\cdots}&{a_{2m}}\\ {\vdots}&{\vdots}&{\ddots}&{\vdots}\\ {a_{m1}}&{a_{m2}}&{\cdots}&{a_{mm}}\\ \end{bmatrix}^n
An=
a11a21⋮am1a12a22⋮am2⋯⋯⋱⋯a1ma2m⋮amm
n
- 核心还是求矩阵的
n
n
n 次幂,如果采用简单的连乘来求解,这个时间复杂度是完全无法接受的,我们联想到之前提到的整数的二分快速幂(整数快速幂),对于矩阵也是同样适用的;
A n = { I n = 0 ( A n − 1 2 ) 2 × A n 为奇数 ( A n 2 ) 2 n 为非零偶数 A^{n} = \begin{cases} I & n = 0\\ (A^{\frac{n-1}{2}})^2 \times A& n 为奇数\\ (A^{\frac{n}{2}})^2 & n 为非零偶数 \end{cases} An=⎩ ⎨ ⎧I(A2n−1)2×A(A2n)2n=0n为奇数n为非零偶数 - 再加上模加、模乘的性质,矩阵同样满足模幂运算,即:
A n m o d M = { I m o d M n = 0 ( A n − 1 2 ) 2 × A m o d M n 为奇数 ( A n 2 ) 2 m o d M n 为非零偶数 A^{n} \mod M = \begin{cases} I \mod M & n = 0\\ (A^{\frac{n-1}{2}})^2 \times A \mod M & n 为奇数\\ (A^{\frac{n}{2}})^2 \mod M & n 为非零偶数 \end{cases} AnmodM=⎩ ⎨ ⎧ImodM(A2n−1)2×AmodM(A2n)2modMn=0n为奇数n为非零偶数 - 如此一来,对于 m m m 阶方阵 A A A,时间复杂度就可以降到 O ( m 3 l o g n ) O(m^3log_n) O(m3logn);
- 模板 C++ 代码:矩阵二分快速幂
五、矩阵快速幂的应用
1、线性递推
1)斐波那契数列
- 还是回到本文开头的那个问题,如何计算斐波那契数列第 n n n 项模上 M M M ?
- 相信聪明的读者已经想到了,我们今天的主角是:矩阵 !
- 我们首先来看递推公式:
f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n−1)+f(n−2) - 然后我们联想到:1 个 2 × 2 2 \times 2 2×2 的矩阵和 1 个 2 × 1 2 \times 1 2×1 的矩阵相乘,得到的还是一个 2 × 1 2 \times 1 2×1 的矩阵 (鬼才能联想到这个啊!!!第一个想出用矩阵的人真 TM 是鬼才!原来 ‘鬼才’ 是这么来的!!!);
- 首先,利用递推公式填充 列向量 和 矩阵 :
[ f ( n ) ? ] = [ 1 1 ? ? ] [ f ( n − 1 ) f ( n − 2 ) ] \left[ \begin{matrix} f(n) \\ ? \end{matrix} \right] = \left[ \begin{matrix} 1 & 1 \\ ? & ?\end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2)\end{matrix} \right] [f(n)?]=[1?1?][f(n−1)f(n−2)] - 接下来利用列向量的传递性把带有问号的列向量补全,得到:
[ f ( n ) f ( n − 1 ) ] = [ 1 1 ? ? ] [ f ( n − 1 ) f ( n − 2 ) ] \left[ \begin{matrix} f(n) \\ f(n-1)\end{matrix} \right] = \left[ \begin{matrix} 1 & 1 \\ ? & ?\end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2)\end{matrix} \right] [f(n)f(n−1)]=[1?1?][f(n−1)f(n−2)] - 再把带有问号的系数矩阵补全,得到:
[ f ( n ) f ( n − 1 ) ] = [ 1 1 1 0 ] [ f ( n − 1 ) f ( n − 2 ) ] \left[ \begin{matrix} f(n) \\ f(n-1)\end{matrix} \right] = \left[ \begin{matrix} 1 & 1 \\ 1 & 0\end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2)\end{matrix} \right] [f(n)f(n−1)]=[1110][f(n−1)f(n−2)] - 然后进行逐步化简,得到:
[ f ( n ) f ( n − 1 ) ] = [ 1 1 1 0 ] [ f ( n − 1 ) f ( n − 2 ) ] = [ 1 1 1 0 ] [ 1 1 1 0 ] [ f ( n − 2 ) f ( n − 3 ) ] = [ 1 1 1 0 ] ⋯ [ 1 1 1 0 ] ⏟ n − 1 [ f ( 1 ) f ( 0 ) ] \begin{aligned} \left[ \begin{matrix} f(n) \\ f(n-1)\end{matrix} \right] &= \left[ \begin{matrix} 1 & 1 \\ 1 & 0\end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2)\end{matrix} \right] \\ &= \left[ \begin{matrix} 1 & 1 \\ 1 & 0\end{matrix} \right] \left[ \begin{matrix} 1 & 1 \\ 1 & 0\end{matrix} \right] \left[ \begin{matrix} f(n-2) \\ f(n-3)\end{matrix} \right] \\ &=\underbrace{ \left[ \begin{matrix} 1 & 1 \\ 1 & 0\end{matrix} \right] {\cdots}\left[ \begin{matrix} 1 & 1 \\ 1 & 0\end{matrix} \right] }_{n-1} \left[ \begin{matrix} f(1) \\ f(0)\end{matrix} \right] \\ \end{aligned} [f(n)f(n−1)]=[1110][f(n−1)f(n−2)]=[1110][1110][f(n−2)f(n−3)]=n−1 [1110]⋯[1110][f(1)f(0)] - 最后,根据矩阵乘法结合律,把前面的矩阵合并,得到:
[ f ( n ) f ( n − 1 ) ] = [ 1 1 1 0 ] n − 1 [ f ( 1 ) f ( 0 ) ] = A n − 1 [ 1 0 ] \begin{aligned} \left[ \begin{matrix} f(n) \\ f(n-1)\end{matrix} \right] &=\left[ \begin{matrix} 1 & 1 \\ 1 & 0\end{matrix} \right]^{n-1}\left[ \begin{matrix} f(1) \\ f(0)\end{matrix} \right] \\ &=A^{n-1}\left[ \begin{matrix} 1 \\ 0 \end{matrix} \right] \end{aligned} [f(n)f(n−1)]=[1110]n−1[f(1)f(0)]=An−1[10] - 那么对于 【例题一】,只要利用矩阵二分快速幂求得 A n − 1 m o d M A^{n-1} \mod M An−1modM ,再乘上初始列向量 [ 1 0 ] \left[ \begin{matrix} 1 \\ 0 \end{matrix} \right] [10],得到的列向量的第一个元素就是问题的解了;
2)乘法系数
【例题三】 f ( 0 ) = 0 , f ( 1 ) = 1 , f ( n ) = a f ( n − 1 ) + b f ( n − 2 ) f(0) = 0, f(1) = 1, f(n) = af(n − 1) + bf(n − 2) f(0)=0,f(1)=1,f(n)=af(n−1)+bf(n−2) 其中 ( n ≥ 2 ) (n ≥ 2) (n≥2),求 f ( n ) m o d M ( M < = 1 0 9 ) f(n) \mod M (M<=10^9) f(n)modM(M<=109);
- 这个问题当
a
=
b
=
1
a = b = 1
a=b=1 的时候就是斐波那契数列了,参照斐波那契数列的矩阵,可以构造如下系数矩阵:
[ a b 1 0 ] \left[ \begin{matrix} a & b \\ 1 & 0\end{matrix} \right] [a1b0] - 然后就是求二分快速幂的问题了,并且可以将情况推广到递推项更多的情况,当前项依赖前多少项的值,就构造多少阶的矩阵;对于递推式只和前几项有关,并且带有乘法系数的,可以参考如下构造方式:
构造方法
- 1)构造一个 k k k 阶零方阵 ( k k k 代表当前项和前面多少项有关);
- 2)第一行填递推系数;
- 3)左下角放置一个 k − 1 k-1 k−1 阶单位矩阵;
递推公式 | 系数矩阵 |
---|---|
f ( n ) = a 0 f ( n − 1 ) f(n) = a_0f(n − 1) f(n)=a0f(n−1) | [ a 0 ] \left[ \begin{matrix} a_0 \end{matrix} \right] [a0] |
f ( n ) = a 0 f ( n − 1 ) + a 1 f ( n − 2 ) f(n) = a_0f(n − 1) + a_1f(n-2) f(n)=a0f(n−1)+a1f(n−2) | [ a 0 a 1 1 0 ] \left[ \begin{matrix} a_0 & a_1 \\ 1 & 0 \end{matrix} \right] [a01a10] |
f ( n ) = a 0 f ( n − 1 ) + a 1 f ( n − 2 ) + a 2 f ( n − 3 ) f(n) = a_0f(n − 1) + a_1f(n-2) + a_2f(n-3) f(n)=a0f(n−1)+a1f(n−2)+a2f(n−3) | [ a 0 a 1 a 2 1 0 0 0 1 0 ] \left[ \begin{matrix} a_0 & a_1 & a_2 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{matrix} \right] a010a101a200 |
f ( n ) = a 0 f ( n − 1 ) + a 1 f ( n − 2 ) + a 2 f ( n − 3 ) + a 3 f ( n − 4 ) f(n) = a_0f(n − 1) + a_1f(n-2) + a_2f(n-3) + a_3f(n-4) f(n)=a0f(n−1)+a1f(n−2)+a2f(n−3)+a3f(n−4) | [ a 0 a 1 a 2 a 3 1 0 0 0 0 1 0 0 0 0 1 0 ] \left[ \begin{matrix} a_0 & a_1 & a_2 & a_3 \\ 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \end{matrix} \right] a0100a1010a2001a3000 |
3)加法系数
【例题四】 已知公式: f ( n ) = { 1 ( n = 1 ) 2 ( n = 2 ) f ( n − 1 ) + 2 f ( n − 2 ) + n 3 ( n > 2 ) f(n) = \begin{cases} 1 & (n = 1) \\ 2 & (n = 2) \\ f(n-1) + 2f(n-2) + n^3 & (n > 2) \end{cases} f(n)=⎩ ⎨ ⎧12f(n−1)+2f(n−2)+n3(n=1)(n=2)(n>2)
-
给出 n n n,求 f ( n ) % 123456789 f(n) \% 123456789 f(n)%123456789;
-
这里的 n 3 n^3 n3 是递推公式的加法系数,沿用之前的方法,构造系数矩阵如下:
[ f ( n ) f ( n − 1 ) ] = [ ? ? ? ? ] [ f ( n − 1 ) f ( n − 2 ) ] \left[ \begin{matrix} f(n) \\ f(n-1)\end{matrix} \right] = \left[ \begin{matrix} ? & ? \\ ? & ?\end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2)\end{matrix} \right] [f(n)f(n−1)]=[????][f(n−1)f(n−2)] -
这时我们发现无法构造这个矩阵,因为多了一个加法系数,于是将列向量补齐,得到如下:
[ f ( n ) f ( n − 1 ) n 3 ] = [ ? ? ? ? ? ? ? ? ? ] [ f ( n − 1 ) f ( n − 2 ) ( n − 1 ) 3 ] \left[ \begin{matrix} f(n) \\ f(n-1) \\ n^3 \end{matrix} \right] = \left[ \begin{matrix} ? & ? & ? \\ ? & ? & ? \\ ? & ? & ? \end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2) \\ (n-1)^3 \end{matrix} \right] f(n)f(n−1)n3 = ????????? f(n−1)f(n−2)(n−1)3 -
将 ( n − 1 ) 3 (n-1)^3 (n−1)3 展开后发现还有 n 2 、 n n^2、n n2、n 以及常数项,这些项无法互相抵消,所以都需要加到列向量中,于是就有了:
[ f ( n ) f ( n − 1 ) n 3 n 2 n 1 ] = [ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ] [ f ( n − 1 ) f ( n − 2 ) ( n − 1 ) 3 ( n − 1 ) 2 ( n − 1 ) 1 ] \left[ \begin{matrix} f(n) \\f(n-1)\\ n^3 \\n^2\\n\\1 \end{matrix} \right]= \left[ \begin{matrix} ? & ? & ? & ? &? & ? \\ ? & ? & ? & ? &? & ? \\ ? & ? & ? & ? &? & ? \\ ? & ? & ? & ? &? & ? \\ ? & ? & ? & ? &? & ? \\? & ? & ? & ? &? & ? \end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2) \\ (n-1)^3 \\ (n-1)^2 \\ (n-1) \\ 1 \end{matrix} \right] f(n)f(n−1)n3n2n1 = ???????????????????????????????????? f(n−1)f(n−2)(n−1)3(n−1)2(n−1)1 -
根据递推公式构造出系数矩阵后二分求解:
[ 1 2 1 3 3 1 1 0 0 0 0 0 0 0 1 3 3 1 0 0 0 1 2 1 0 0 0 0 1 1 0 0 0 0 0 1 ] \left[ \begin{matrix} 1 & 2 & 1 & 3 & 3 & 1 \\ 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 3 & 3 & 1\\0 & 0 & 0 &1 & 2 & 1 \\ 0 & 0 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 &0 & 0 & 1\end{matrix} \right] 110000200000101000303100303210101111
2、数列前缀和
- 数列前缀和就是给定一个数列
f
(
i
)
f(i)
f(i) 和一个次幂
k
k
k,求:
S ( i ) = ∑ i = 1 N f ( i ) k S(i) = \sum_{i=1}^{N}f(i)^k S(i)=i=1∑Nf(i)k
1)一次幂前缀和
【例题五】 T [ 0 ] = T [ 1 ] = T [ 2 ] = 1 T[0] = T[1] = T[2] = 1 T[0]=T[1]=T[2]=1 T [ n ] = T [ n − 1 ] + T [ n − 2 ] + T [ n − 3 ] ( n > = 3 ) T[n] = T[n - 1] + T[n - 2] + T[n - 3] (n >= 3) T[n]=T[n−1]+T[n−2]+T[n−3](n>=3)
- 给定 a 和 b 求 ( T [ a ] + T [ a + 1 ] + . . . + T [ b ] ) % 1 , 000 , 000 , 007 (T[a] + T[a + 1] + ... + T[b]) \% 1,000,000,007 (T[a]+T[a+1]+...+T[b])%1,000,000,007
- 首先,对于求部分和的问题,我们可以转化成前缀和,即:
- 令 S [ n ] = ∑ i = 0 n T [ i ] S[n] = \sum_{i=0}^n{T[i]} S[n]=∑i=0nT[i],则 ( T [ a ] + T [ a + 1 ] + . . . + T [ b ] ) = S [ b ] − S [ a − 1 ] (T[a] + T[a + 1] + ... + T[b]) = S[b] - S[a-1] (T[a]+T[a+1]+...+T[b])=S[b]−S[a−1],于是问题转化成求 S [ n ] S[n] S[n] 的问题;
- 首先,我们根据递推公式得到:
S [ n ] = ∑ i = 0 n T [ i ] = S [ n − 1 ] + T [ n ] = S [ n − 1 ] + T [ n − 1 ] + T [ n − 2 ] + T [ n − 3 ] \begin{aligned} S[n] &= \sum_{i=0}^n{T[i]} \\ &= S[n-1] + T[n]\\ &= S[n-1] + T[n - 1] + T[n - 2] + T[n - 3] \end{aligned} S[n]=i=0∑nT[i]=S[n−1]+T[n]=S[n−1]+T[n−1]+T[n−2]+T[n−3] - 于是,我们可以构造如下系数矩阵,并且把上述的递推公式填充到矩阵系数和列向量中:
[ S [ n ] ? ? ? ] = [ 1 1 1 1 ? ? ? ? ? ? ? ? ? ? ? ? ] [ S [ n − 1 ] T [ n − 1 ] T [ n − 2 ] T [ n − 3 ] ] \begin{aligned} \left[ \begin{matrix} S[n] \\ ? \\ ? \\ ? \end{matrix}\right] &= \left[ \begin{matrix} 1 & 1 & 1 & 1 \\ ? & ? & ? & ? \\ ? & ? & ? & ? \\ ? & ? & ? & ? \end{matrix}\right] \left[ \begin{matrix} S[n-1] \\ T[n-1] \\ T[n-2] \\ T[n-3] \end{matrix}\right] \end{aligned} S[n]??? = 1???1???1???1??? S[n−1]T[n−1]T[n−2]T[n−3] - 接着,利用列向量传递性把参数补全,再利用递推公式补全系数矩阵,如下:
[ S [ n ] T [ n ] T [ n − 1 ] T [ n − 2 ] ] = [ 1 1 1 1 0 1 1 1 0 1 0 0 0 0 1 0 ] [ S [ n − 1 ] T [ n − 1 ] T [ n − 2 ] T [ n − 3 ] ] \begin{aligned} \left[ \begin{matrix} S[n] \\ T[n] \\ T[n-1] \\ T[n-2] \end{matrix}\right] &= \left[ \begin{matrix} 1 & 1 & 1 & 1 \\ 0 & 1 & 1 & 1 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \end{matrix}\right] \left[ \begin{matrix} S[n-1] \\ T[n-1] \\ T[n-2] \\ T[n-3] \end{matrix}\right] \end{aligned} S[n]T[n]T[n−1]T[n−2] = 1000111011011100 S[n−1]T[n−1]T[n−2]T[n−3]
2)二次幂前缀和
【例题六】
- A ( 0 ) = 1 , A ( 1 ) = 1 A(0) = 1 , A(1) = 1 A(0)=1,A(1)=1 A ( n ) = X ∗ A ( n − 1 ) + Y ∗ A ( n − 2 ) ( n > = 2 ) A(n) = X * A(n - 1) + Y * A(n - 2) (n >= 2) A(n)=X∗A(n−1)+Y∗A(n−2)(n>=2) 求 S ( n ) = ∑ i = 0 n A ( i ) 2 S(n) = \sum_{i=0}^{n}A(i)^2 S(n)=i=0∑nA(i)2
- 首先利用递推式,可以得出
A
(
n
)
2
A(n)^2
A(n)2 的递推式如下:
A ( n ) 2 = ( X ∗ A ( n − 1 ) + Y ∗ A ( n − 2 ) ) 2 = X 2 A ( n − 1 ) 2 + 2 X Y A ( n − 1 ) A ( n − 2 ) + Y 2 A ( n − 2 ) 2 \begin{aligned} A(n)^2 &= (X * A(n - 1) + Y * A(n - 2))^2 \\ &= X^2 A(n - 1)^2 + 2XYA(n - 1)A(n - 2) + Y^2 A(n - 2)^2 \end{aligned} A(n)2=(X∗A(n−1)+Y∗A(n−2))2=X2A(n−1)2+2XYA(n−1)A(n−2)+Y2A(n−2)2 -
S
(
n
)
S(n)
S(n) 满足等式:
S ( n ) = S ( n − 1 ) + A ( n ) 2 = S ( n − 1 ) + X 2 A ( n − 1 ) 2 + 2 X Y A ( n − 1 ) A ( n − 2 ) + Y 2 A ( n − 2 ) 2 \begin{aligned} S(n) &= S(n-1) + A(n)^2 \\ &= S(n-1) + X^2 A(n - 1)^2 + 2XYA(n - 1)A(n - 2) + Y^2 A(n - 2)^2 \end{aligned} S(n)=S(n−1)+A(n)2=S(n−1)+X2A(n−1)2+2XYA(n−1)A(n−2)+Y2A(n−2)2 - 思路还是一样,首先根据递推公式构造列向量和系数矩阵:
[ S ( n ) ? ? ? ] = [ 1 X 2 2 X Y Y 2 ? ? ? ? ? ? ? ? ? ? ? ? ] [ S ( n − 1 ) A ( n − 1 ) 2 A ( n − 1 ) A ( n − 2 ) A ( n − 2 ) 2 ] \begin{aligned} \left[ \begin{matrix} S(n) \\ ? \\ ? \\ ? \end{matrix}\right] &= \left[ \begin{matrix} 1 & X^2 & 2XY & Y^2 \\ ? & ? & ? & ? \\ ? & ? & ? & ? \\ ? & ? & ? & ? \end{matrix}\right] \left[ \begin{matrix} S(n-1) \\ A(n-1)^2 \\ A(n-1)A(n-2) \\ A(n-2)^2 \end{matrix}\right] \end{aligned} S(n)??? = 1???X2???2XY???Y2??? S(n−1)A(n−1)2A(n−1)A(n−2)A(n−2)2 - 然后补充列向量,再根据列向量的递推关系得到完整的系数矩阵:
[ S ( n ) A ( n ) 2 A ( n ) A ( n − 1 ) A ( n − 1 ) 2 ] = [ 1 X 2 2 X Y Y 2 0 X 2 2 X Y Y 2 0 X Y 0 0 1 0 0 ] [ S ( n − 1 ) A ( n − 1 ) 2 A ( n − 1 ) A ( n − 2 ) A ( n − 2 ) 2 ] = [ 1 X 2 2 X Y Y 2 0 X 2 2 X Y Y 2 0 X Y 0 0 1 0 0 ] n − 1 [ S ( 1 ) A ( 1 ) 2 A ( 1 ) A ( 0 ) A ( 0 ) 2 ] = A n − 1 [ 2 1 1 1 ] \begin{aligned} \left[ \begin{matrix} S(n) \\ A(n)^2 \\ A(n)A(n-1) \\ A(n-1)^2 \end{matrix}\right] &= \left[ \begin{matrix} 1 & X^2 & 2XY & Y^2 \\ 0 & X^2 & 2XY & Y^2 \\ 0 & X & Y & 0 \\ 0 & 1 & 0 & 0 \end{matrix}\right] \left[ \begin{matrix} S(n-1) \\ A(n-1)^2 \\ A(n-1)A(n-2) \\ A(n-2)^2 \end{matrix}\right] \\ &=\left[ \begin{matrix} 1 & X^2 & 2XY & Y^2 \\ 0 & X^2 & 2XY & Y^2 \\ 0 & X & Y & 0 \\ 0 & 1 & 0 & 0 \end{matrix}\right]^{n-1} \left[ \begin{matrix} S(1) \\ A(1)^2 \\ A(1)A(0) \\ A(0)^2 \end{matrix}\right] \\ &= A^{n-1} \left[ \begin{matrix} 2 \\ 1 \\ 1 \\ 1\end{matrix}\right] \\ \end{aligned} S(n)A(n)2A(n)A(n−1)A(n−1)2 = 1000X2X2X12XY2XYY0Y2Y200 S(n−1)A(n−1)2A(n−1)A(n−2)A(n−2)2 = 1000X2X2X12XY2XYY0Y2Y200 n−1 S(1)A(1)2A(1)A(0)A(0)2 =An−1 2111
3)K 次幂前缀和
【例题七】
F
(
1
)
=
f
1
,
F
(
2
)
=
f
2
,
F
(
n
)
=
a
F
(
n
−
1
)
+
b
F
(
n
−
2
)
F(1) = f_1, F(2) = f_2, F(n) = aF(n-1) + bF(n-2)
F(1)=f1,F(2)=f2,F(n)=aF(n−1)+bF(n−2)
- 给定 f 1 、 f 2 、 a 、 b 、 n , m , k ( k < = 50 ) f_1、f_2、a、b、n,m,k(k <= 50) f1、f2、a、b、n,m,k(k<=50),求 ∑ i = 1 n F ( i ) k m o d m \sum_{i=1}^n F(i)^k \mod m ∑i=1nF(i)kmodm
- 这个问题就留给聪明的读者吧 ^ _ ^【先想一下,实在想不出来就去看讲解吧:传送门】
3、矩阵 K 次幂前缀和
【例题八】 给出一个 n × n n × n n×n 的矩阵 A A A 和两个正整数 k , m k, m k,m, 求 S ( k ) = ( A + A 2 + A 3 + … + A k ) m o d m S(k) = (A + A^2 + A^3 + … + A^k) \mod m S(k)=(A+A2+A3+…+Ak)modm。
- 难度:★★☆☆☆
- 题解:首先,如果
k
k
k 为偶数,则
S
(
k
)
S(k)
S(k) 满足如下递推式:
S ( k ) = ( A + A 2 + A 3 + … + A k ) = A ∗ S ( k − 1 ) + A \begin{aligned} S(k) &= (A + A^2 + A^3 + … + A^k) \\ &= A * S(k-1) + A \end{aligned} S(k)=(A+A2+A3+…+Ak)=A∗S(k−1)+A - 根据递推式,生成系数矩阵,这里的系数又是一个矩阵:
[ S ( k ) ? ] = [ A A ? ? ] [ S ( k − 1 ) I ] \left[ \begin{matrix} S(k) \\ ? \end{matrix} \right] = \left[ \begin{matrix} A & A \\ ? & ?\end{matrix} \right] \left[ \begin{matrix} S({k-1}) \\ I \end{matrix} \right] [S(k)?]=[A?A?][S(k−1)I] - 最后,填充 ?项,构造的矩阵如下(
A
A
A 为原矩阵,
O
O
O 为零矩阵,
I
I
I 为单位矩阵):
[ S ( k ) I ] = [ A A O I ] [ S ( k − 1 ) I ] = [ A A O I ] k − 1 [ S ( 1 ) I ] = B k − 1 [ A I ] \begin{aligned} \left[ \begin{matrix} S(k) \\ I \end{matrix} \right] &= \left[ \begin{matrix} A & A \\ O & I\end{matrix} \right]\left[ \begin{matrix} S(k-1) \\ I \end{matrix} \right] \\ &=\left[ \begin{matrix} A & A \\ O & I\end{matrix} \right]^{k-1}\left[ \begin{matrix} S(1) \\ I \end{matrix} \right] \\ &=B^{k-1}\left[ \begin{matrix} A \\ I \end{matrix} \right] \end{aligned} [S(k)I]=[AOAI][S(k−1)I]=[AOAI]k−1[S(1)I]=Bk−1[AI] - 矩阵 B B B 的阶数为矩阵 A A A 的两倍,利用矩阵二分求解 B B B 的 k − 1 k-1 k−1 次幂后再乘上列向量,得到的列向量的上半部分就是所求的 S ( k ) S(k) S(k)。
4、动态规划配合构造矩阵
1)路径数 - 转化成图
【例题九】 给定一个 n ( n < = 100 ) n (n<=100) n(n<=100) 个顶点的有向图,然后一串询问,求 a a a 到 b b b 经过 k k k ( 0 < = a , b < n , k < = 1 0 9 ) (0<=a,b<n, k<=10^9) (0<=a,b<n,k<=109) 步的方案数;
- 令
f
(
n
,
v
)
f(n, v)
f(n,v) 为从某个点出发,经过
n
n
n 步以后到达
v
v
v 的方案数,那么有状态转移如下:
f ( n , v ) = { 1 n = 0 , v = a 0 n = 0 , v ≠ a ∑ u − > v f ( n − 1 , u ) n > 0 f(n,v) =\begin{cases} 1 & n = 0, v=a\\ 0 & n = 0, v \not= a\\ \sum_{}^{u->v}f(n-1,u) & n > 0 \end{cases} f(n,v)=⎩ ⎨ ⎧10∑u−>vf(n−1,u)n=0,v=an=0,v=an>0 - 举个例子,有向图如下:
- 这个图的邻接矩阵如下(
A
[
u
]
[
v
]
表示
u
到
v
有多少条边
A[u][v] 表示 u 到 v 有多少条边
A[u][v]表示u到v有多少条边):
A = [ 0 1 2 1 0 0 0 0 0 ] A = \left[ \begin{matrix} 0 & 1 & 2\\ 1 & 0 & 0 \\ 0 & 0 & 0 \end{matrix} \right] A= 010100200 - 根据状态转移构造出如下矩阵递推关系:
[ f ( n , 0 ) f ( n , 1 ) f ( n , 2 ) ] = [ 0 1 0 1 0 0 2 0 0 ] [ f ( n − 1 , 0 ) f ( n − 1 , 1 ) f ( n − 1 , 2 ) ] \left[ \begin{matrix} f(n,0)\\ f(n,1) \\ f(n,2) \end{matrix} \right] = \left[ \begin{matrix} 0 & 1 & 0\\ 1 & 0 & 0 \\ 2 & 0 & 0 \end{matrix} \right] \left[ \begin{matrix} f(n-1,0)\\ f(n-1,1) \\ f(n-1,2) \end{matrix} \right]\\ f(n,0)f(n,1)f(n,2) = 012100000 f(n−1,0)f(n−1,1)f(n−1,2) - 观察发现系数矩阵和正好是邻接矩阵的转置,于是根据邻接矩阵建立反图,再用 k k k 次幂二分求解,最后乘上一个列向量,列向量第 a a a 行为 1 1 1,其他都为 0 0 0,得到的列向量的第 b b b 行就是所求的 a a a 到 b b b 经过 k k k 步 的方案数;
2)数位动态规划
【例题十】 一个由 1 1 1 和 0 0 0 组成的字符串,任何子串都不能包含 101 和 111 101 和 111 101和111,求这样的长度为 L ( L < = 1 0 6 ) L (L <= 10^6) L(L<=106) 的字符串的种数;
- 令 f ( n , x ) f(n, x) f(n,x) 表示长度为 n n n,最后三位为 x x x 的合法字符串方案数;
- 例如
f
(
35
,
100
)
f(35, 100)
f(35,100) 代表长度为 35,最后三位为 110 的方案数,那么有状态转移方程:
f ( 35 , 100 ) = f ( 34 , 010 ) + f ( 34 , 110 ) f(35, 100) = f(34, 010) + f(34, 110) f(35,100)=f(34,010)+f(34,110)
- 三位的 ‘01’ 串总共 8 8 8 种情况,去掉两种不合法的状态,其他状态的状态转移图如下:
- 通过邻接矩阵构造出转置矩阵作为系数矩阵,求转换成了从 a a a 点到 b b b 点经过 k k k 步的路径数问题了;
5、双变量交换递推
【例题十一】
- 给定 n ( n < = 1 0 9 ) n(n <= 10^9) n(n<=109),求 ⌊ ( 2 + 3 ) 2 n ⌋ m o d 1024 \lfloor (\sqrt 2 + \sqrt 3)^{2n} \rfloor \mod 1024 ⌊(2+3)2n⌋mod1024
- 首先,令
f
(
n
)
=
(
2
+
3
)
2
n
=
(
5
+
2
6
)
n
f(n) = {(\sqrt{2}+\sqrt{3})}^{2n} = (5+2\sqrt{6})^n
f(n)=(2+3)2n=(5+26)n,无论 n 多大,一定可以表示成
f
(
n
)
=
A
n
+
B
n
6
f(n) = A_n + B_n\sqrt{6}
f(n)=An+Bn6,则有如下递推式:
f ( n ) = A n + B n 6 = ( A n − 1 + B n − 1 6 ) ( 5 + 2 6 ) = ( 5 A n − 1 + 12 B n − 1 ) + ( 2 A n − 1 + 5 B n − 1 ) 6 \begin{aligned} f(n) &= A_n + B_n\sqrt{6} \\ &= (A_{n-1} + B_{n-1}\sqrt{6})(5+2\sqrt{6})\\ &= (5A_{n-1} + 12B_{n-1}) + (2A_{n-1} + 5B_{n-1})\sqrt{6} \end{aligned} f(n)=An+Bn6=(An−1+Bn−16)(5+26)=(5An−1+12Bn−1)+(2An−1+5Bn−1)6 - 表示成矩阵的形式如下:
[ A n B n ] = [ 5 12 2 5 ] [ A n − 1 B n − 1 ] = [ 5 12 2 5 ] n − 1 [ 5 2 ] \left[ \begin{matrix} A_n \\B_n\end{matrix} \right]= \left[ \begin{matrix} 5 & 12\\ 2 & 5\end{matrix} \right] \left[ \begin{matrix} A_{n-1} \\B_{n-1} \end{matrix} \right]= \left[ \begin{matrix} 5 & 12\\ 2 & 5\end{matrix} \right]^{n-1} \left[ \begin{matrix} 5 \\2 \end{matrix} \right] [AnBn]=[52125][An−1Bn−1]=[52125]n−1[52]
又由于 ( 5 + 2 6 ) ( 5 − 2 6 ) = 1 (5+2\sqrt{6})(5-2\sqrt{6})=1 (5+26)(5−26)=1,得到 ( 5 + 2 6 ) n ( 5 − 2 6 ) n = 1 (5+2\sqrt{6})^n(5-2\sqrt{6})^n=1 (5+26)n(5−26)n=1,则 ( A n + B n 6 ) ( A n − B n 6 ) = 1 (A_n+B_n\sqrt{6})(A_n-B_n\sqrt{6})=1 (An+Bn6)(An−Bn6)=1,得到:
6 B n 2 = A n 2 − 1 6B_n^2 = A_n^2 - 1 6Bn2=An2−1,从而推导出 B n 6 = A n 2 − 1 B_n\sqrt{6} = \sqrt{A_n^2 - 1} Bn6=An2−1,于是 B n 6 B_n\sqrt{6} Bn6 的整数部分就是 A n − 1 A_n-1 An−1,所以我们要求的答案就是 ( 2 A n − 1 ) % 1024 (2A_n-1) \% 1024 (2An−1)%1024,矩阵求解 A n A_n An;
6、扩展欧拉定理配合降幂
【例题十二】 F ( 0 ) = a , F ( 1 ) = b , F ( n ) = F ( n − 1 ) ∗ F ( n − 2 ) ( n > 1 ) ,给定 a 、 b 、 n ( n < = 1 0 9 ) ,求 F ( n ) m o d 1000000007 F(0) = a, F(1) = b, F(n) = F(n-1) * F(n-2) ( n > 1 ),给定 a、b、n(n <=10^9),求 F(n) \mod 1000000007 F(0)=a,F(1)=b,F(n)=F(n−1)∗F(n−2)(n>1),给定a、b、n(n<=109),求F(n)mod1000000007
-
根据递推公式容易得到 F ( n ) = a f ( n − 2 ) b f ( n − 1 ) F(n) = a^{f(n-2)}b^{f(n-1)} F(n)=af(n−2)bf(n−1),其中 f ( 0 ) = f ( 1 ) = 1 f(0)=f(1)=1 f(0)=f(1)=1,且满足 f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n−1)+f(n−2),即斐波那契数列;
-
令 G ( n , k ) = k f ( n ) m o d 1000000007 G(n, k) = k^{f(n)} \mod1000000007 G(n,k)=kf(n)mod1000000007,那么我们只需要求出 G ( n , k ) G(n, k) G(n,k) 就可以求得原式的解;
-
扩展欧拉定理
a b m o d c = { a b m o d φ ( c ) m o d c g c d ( a , c ) = 1 a b m o d c g c d ( a , c ) ≠ 1 , b < φ ( c ) a b m o d φ ( c ) + φ ( c ) m o d c g c d ( a , c ) ≠ 1 , b > = φ ( c ) a^{b} \mod c = \begin {cases} a^{b \mod \varphi(c)} \mod c & { gcd(a,c)=1} \\ a^{b} \mod c & { gcd(a,c) \neq 1 ,b < \varphi(c)} \\ a^{b \mod \varphi(c) + \varphi(c)} \mod c & { gcd(a,c) \neq 1 ,b >= \varphi(c)} \\ \end {cases} abmodc=⎩ ⎨ ⎧abmodφ(c)modcabmodcabmodφ(c)+φ(c)modcgcd(a,c)=1gcd(a,c)=1,b<φ(c)gcd(a,c)=1,b>=φ(c) -
当 f ( n ) < φ ( 1000000007 ) f(n) < \varphi(1000000007) f(n)<φ(1000000007) 说明 n 比较小,直接求递推求出来即可;
-
当 f ( n ) > = φ ( 1000000007 ) f(n) >= \varphi(1000000007) f(n)>=φ(1000000007) 时,根据扩展欧拉定理,得到:
G ( n , k ) = k f ( n ) m o d 1000000007 = k f ( n ) m o d φ ( 1000000007 ) + φ ( 1000000007 ) m o d 1000000007 \begin{aligned} G(n, k) &= k^{f(n)} \mod1000000007 \\ &= k^{f(n) \mod \varphi(1000000007) + \varphi(1000000007)} \mod1000000007 \end{aligned} G(n,k)=kf(n)mod1000000007=kf(n)modφ(1000000007)+φ(1000000007)mod1000000007 -
f ( n ) f(n) f(n) 是最基本的斐波那契数列,直接用矩阵二分求解即可;
7、其他算法配合矩阵优化
1)循环节降幂
- 对于矩阵
A
A
A,要求
A
k
m
o
d
M
A^k \mod M
AkmodM,如果
M
M
M 比较小,可以暴力计算出
A
t
m
o
d
M
=
I
A^t \mod M = I
AtmodM=I,这里的
t
t
t 就是矩阵循环节,然后就有:
A k m o d M = A ( k m o d t ) m o d M A^k \mod M = A^{(k \mod t)} \mod M AkmodM=A(kmodt)modM
2)AC自动机
- 利用 AC 自动机 构造 trie 图,并且在 trie 图上进行矩阵二分;
3)搜索
- 利用搜索 ( B F S / D F S ) (BFS / DFS) (BFS/DFS) 枚举所有状态转移的情况,然后进行矩阵二分;