DP优化——矩阵优化

矩阵优化

矩阵快速幂,相信大家已经会了

还是要说两句:矩阵乘法的特点是,不满足交换律,满足结合律,满足分配律

模板题:斐波那契数列

变形

缺什么补什么,有不确定的信息就先将递推式写出来,然后根据具体情况加维

带常数项 k

递推方程:\(f_{n}=f_{n-1}+f_{n−2}+k\)

\[f_{n}=\begin{vmatrix}f_{n}&f_{n-1}&k\end{vmatrix} , base=\begin{vmatrix}1&1&0\\1&0&0\\1&0&1\end{vmatrix} \]

带未知数项n

递推方程:\(f_{n}=f_{n−1}+f_{n−2}+n\)

\[f_{n}=\begin{vmatrix}f_{n}&f_{n-1}&n&1\end{vmatrix} , base=\begin{vmatrix}1&1&0&0\\1&0&0&0\\1&0&1&0\\1&0&1&1\end{vmatrix} \]

求和

递推方程:\(f_{n}=f_{n-1}+f_{n−2}\)

求:\(\sum\limits_{i=1}^{n}{f_{i}}\)

暴力计算\(n\)次得出\(f_i\)数组肯定是不行的,但可以尝试将\(S_n\)放入矩阵跟随着\(f_n\)一起递推

于是得到一个式子:\(S_n=S_{n-1}+f_n\)

\[f_{n}=\begin{vmatrix}f_{n}&f_{n-1}&S_{n-1}\end{vmatrix} , base=\begin{vmatrix}1&1&1\\1&0&0\\0&0&1\end{vmatrix} \]

例题

1.连续幂次和

给定一个\(n×n\)的矩阵\(A\)和一个整数\(k\),求\(\sum\limits_{i=1}^{k}{A^{i}}\)

解法:分治

对于单个\(A^i\)可以通过\(log\)次转移得到,需要计算多个时就需要再次分治

原理:\(A^1+A^2+A^3...A^n=A^1+A^2+A^3+...+A^{mid}+A^{mid}∗(A^1+A^2+A^3+...+A^{mid})\)

每次分治时计算一下\(mid\),递归计算\(\sum\limits_{i=1}^{mid}{A^i}\)\(log\)次乘法计算\(A^{mid}\),另一半可直接得出(当\(k\)为奇数时还需计算\(A^k\)

时间复杂度:\(n^3log_2^k\)

2.有向图中求合法路径方案数

远古无来源题目

给出一张\(n\)个点(从\(1\)\(n\)编号)\(m\)条边有向图,每次询问求从\(s\)恰好走\(k\)步到达\(t\)的方案数,重边视作一条路径,每条边可重复走

\(f_{k,i,j}\)表示从点\(i\)到达点 \(j\)恰好走\(k\)步的方案数

\(k\)较小时可以使用\(bfs+dp\),若存在一条边\(x->j\),则\(f_{k,i,j}+=f_{k-1,i,x}\)

但如果\(k<=1e9\)就无法解决了

若用邻接矩阵\(a(i,j)\)来表示点\(i\)\(j\)之间是否连边,那么根据上述转移式子可得: \(f_{k,i,j}\)=\(\sum\limits_{x=1}^{n}{f_{k-1,i,x}*a_{x,j}}\)

由于询问是不定向的,起点和终点可能是 \([1,n]\)中的任意一个,所以答案矩阵应包含\(n^2\)个信息,其中A(k)中的第\(i\)行第\(j\)列表示\(f_{k,i,j}\),即用\(A(k)\)表示恰好走\(k\)步的答案矩阵

所以对于每条边\(i->j\),使累乘矩阵中第\(i\)行第\(j\)列的数为\(1\),最后直接求一个\(k\)次幂即可

\[A_{k}=\begin{vmatrix}f_{k,1,1}&f_{k,1,2}&...&f_{k,1,n}\\f_{k,2,1}&f_{k,2,2}&...&f_{k,2,n}\\...&...&...&...\\f_{k,n,1}&f_{k,n,2}&...&f_{k,n,n}\end{vmatrix} \]

延伸

  1. 询问改为:求走的步数不超过\(k\)的方案数,其他条件不变

    直接套用变形中的求和即可

  2. 在每条边上放一些物品,给出起点,求步数不超过\(k\)且收集完全部物品的方案数(收集一条边上的所有物品也要一步代价)

    题解

3.数学作业

小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:

给定正整数 n 和 m,要求计算$ Concatenate(1\dots n)\bmod m$ 的值,其中\(Concatenate(1\dots n)\)是将所有正整数 \(1,2,\dots,n\) 顺序连接起来得到的数。小 C 想了大半天终于意识到这是一道不可能手算出来的题目,于是他只好向你求助,希望你能编写一个程序帮他解决这个问题。

数据范围: \(1\le n\le 10^{18}\)\(1\le m\le 10^9\)

我们设前\(i\)个数的答案为\(f_i\)

那么可以列出如下转移方程:

\(f_i=f_{i-1}+10^{\left\lfloor\log_{10}i\right\rfloor+1}+i\)

发现第\(i\)项之和第\(i-1\)项有关,可以考虑矩阵快速幂优化递推

\[\begin{vmatrix}f_n\\n\\1\end{vmatrix} = \begin{vmatrix}10^k&1&1\\0&1&1\\0&0&1\end{vmatrix} * \begin{vmatrix}f_{n-1}\\n-1\\1\end{vmatrix} \]

但是我们发现,指数k的值是会变化的,没法直接矩乘.然而它的值一共只有 18种,所以我们直接枚举k然后分块矩乘后合并

题单

资料

https://blog.csdn.net/rowanhaoa/article/details/21024093

posted @ 2020-08-10 13:03  ZTC_ZTC  阅读(102)  评论(0编辑  收藏  举报