矩阵快速幂学习笔记
这矩阵快速幂多是一件美事啊
只用推式子,而且这式子也是十分好推。
是个人第一眼看到这题,第一眼都会想着递推。但是如果真这么简单的话,它就不会是绿题了。我们一看数据范围:n≤263。O(n) 不给你全部炸完?
先来推式子:fi=fi−1+fi−2,fi−1=fi−1。我们把他整理一下:
{fifi−1=1×fi−1+1×fi−2=1×fi−1+0×fi−2我们一看,这可以用矩阵来表示啊:
[1110][fi−1fi−2]=[fifi−1]而我们又看:
[1110]1[fi−1fi−2]=[fifi−1][1110]2[fi−2fi−3]=[fifi−1]发现什么端倪没有?如果我们一直往前推,定能推到 [f2f1]。而我们看:往前推一次,要乘转矩阵的 1 次方,fi 变成 fi−1。而我们最终要从 fn 变成 f2,也就是 fn−(n−2),那么我们就可以知道,推到 [f2f1] 要用原矩阵 [11] 乘转移矩阵 [1110] 的 n−2 次方。也就是 [fnfn−1]=[1110]n−2[11]。那么我们就可以用矩阵快速幂来做咯。注意:矩阵乘法没有交换律,一定注意矩阵乘法的顺序。
code:
我们看:n≤100,用邻接矩阵存图吧,在邻接矩阵中,i 到 j 有边,disi,j 就为 1,反之为 0。然后我们就可以写出这样的一个柿子:
fi,j=k=1⨁nfj−1,k×disk,i我们看,这玩意,似乎有点像什么?矩阵乘法啊。只不过是把求和换成了异或而已。然后,我们就可以定义新的矩阵乘法了。但是,fi,j 和式子里的顺序似乎反了,于是我们直接把 i,j 的定义反一下:
fi,j=k=1⨁nfi−1,k×disk,j也是十分顺眼。
然后,我们看,矩阵乘法,那不得用快速幂啊,但是快速幂要用到乘法结合律,我们来看看这玩意有没有结合律。啊,好像没有。但是不用快速幂又没法做啊,硬着头皮证一下吧。
发现 dis 一定是一个 01
矩阵,似乎这个特殊性质有点用?
我们要证结合律,那么就是要证 (A×B)×C=A×(B×C)。根据定义,(A×B)×C 的 x,y 处的元素是 i=1⨁n(j=1⨁nAx,j×Bj,i)×Ci,y。但是异或是没有分配律的,所以这括号现在还不能拆,得三思而后行。我们看 Ci,y 只有 0 和 1 两种情况,分类讨论一下?
- 当 Ci,y=0 时,那一大坨都给乘没了,所以可以拆。
- 当 Ci,y=1 时,乘完还是那坨,也可以。
综上所述,那个括号是可以拆的,当且仅当 C 是 01
矩阵时。巧了,我们的邻接矩阵就是 01
矩阵,这不爽了?
根据上面推的式子:fi=fi−1×dis,其中 fi 与 fi−1 都是 1 行 n 列的矩阵。那么显然有:fi=f0×disi。这不就是快速幂吗?但是,我们看,查询有 100 个,而矩阵乘法是 O(n3) 的,加上快速幂的总复杂度就是 O(qn3logai),似乎不大行,于是我们考虑预处理。把 dis 的 2x 都预处理出来,查询的时候循坏利用,就可以了。
code: