用矩阵乘法优化递推

(有关矩阵乘法的基本规则请自行搜索)

引例:求斐波那契数列的第 n 项 mod 1000000007 的值,n <= 1018

分析:斐波那契数列的递推式为 f(n) = f(n-1)+f(n-2),直接循环求出 f(n) 的时间复杂度是 O(n),对于题目中的数据范围显然无法承受。很明显我们需要对数级别的算法。

由于 f(n) = 1*f(n-1) + 1*f(n-2) 这样的形式很类似于矩阵的乘法,所以我们可以先把这个问题复杂化一下,将递推求解 f(n) 与 f(n-1) 的过程看作是某两个矩阵相乘的结果,式子如下:

[ f(n-2), f(n-1) ]

*

[ 0, 1 ]

[ 1, 1 ]

=

[ f(n-1), f(n-2)+f(n-1)=f(n) ]

所以我们只要不断地乘以上面式子中的第二个矩阵(也就是第二个矩阵的幂)就能够不断递推得到 f(n)。但是这样于解题没有丝毫益处,反而使得常数变得更大(矩阵乘法的复杂度为立方级别)。所以我们就要利用矩阵乘法的一条重要性质:结合律。即矩阵 (A*B)*C = A*(B*C),证明过程可参见 2008 年国家集训队俞华程的论文。

有了结合律我们就可以用快速幂计算矩阵的幂,问题的复杂度顺利降到了 O(logn)。

?

:Sam 数

Sam 数是指相邻的两位数字相差不超过 2 的数。求长度为 n 的 Sam 数有多少个。输出对 1000000007 取余后的结果。n <= 10^18。

分析:这个数据范围很吓人,所以必须要 O(logn) 的算法。

首先,递推式很明显:

用 f(i, j) 表示第 j 位为 i 时总的个数(先不考虑各种特殊情况),则

f(i, j) = f(i-2, j-1) + f(i-1, j-1) + f(i, j-1) + f(i+1, j-1) + f(i+2, j-1)

我们考虑这样一个矩阵 A:

[ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]

这个 1*10 矩阵表示当第一位为 i 且一共只有 1 位时的方案数。

考虑另一个矩阵 B:

这个矩阵的第 i 行
第 j 列
表示当某一位为 j,相邻一位取 i 时的方案数。

我们将矩阵 A 与 B 相乘一次,可以得到一个 1*10 的矩阵,很明显,这个矩阵的第 i 个元素的值表示当第一位为 i 且一共有 2 位时的方案数,那么矩阵的元素和即 n=2 时的结果。

同理,将 A 不断地与 B 相乘,对于 n,最终得到的矩阵为 A * (B ^ n-1) 的结果,这个矩阵的元素和即最终答案。注意 n=1 的时候特判,这时 0 也算一个方案,所以答案为 10。

用矩阵乘法优化递推,布布扣,bubuko.com

时间: 2024-08-02 22:58:25

用矩阵乘法优化递推的相关文章

略谈矩阵乘法优化递推

1.矩阵基本概念: 矩阵大概就是二维数组存储的样子,然后每一个地方都有元素. 例如: 然后是矩阵的乘法: 矩阵的了解就到这里了 2.引入 求斐波那契数列第n项,n<=10^9. 1.通项公式: 不足: 要求n次方. 虽说n次方可以log2出解,但是精度问题值得考量. 2.矩阵快速幂:              先在考虑将A矩阵转化成B矩阵. 发现有这样一个转移矩阵. 使得 所以我们可以用矩阵解决了.即:   不过单纯这么用矩阵显然是远远不够的,因为一步一步是O(n)的,因此我们要用快速幂,如下伪

利用矩阵乘法计算递推数列的某一项

形态形成场(矩阵乘法优化dp)

形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 \(A=12312301231230,B=1231230,C=123\).现在对于给定的替换式,求字符 AA 所代表的串有多少子串满足: 这个子串为单个字符\(0\)或没有前导\(0\). 把这个子串看作一个十进制数后模\(n\)等于\(0\). 答案对\(r\)取模.对于100%的数据,$2 \l

[POJ 3150] Cellular Automaton (矩阵快速幂 + 矩阵乘法优化)

Cellular Automaton Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 3048   Accepted: 1227 Case Time Limit: 2000MS Description A cellular automaton is a collection of cells on a grid of specified shape that evolves through a number of dis

2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)

题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据是不可能会有的,而我们一开始一直在想极端数据能接受的方法......后来看了鹏哥的做法,就是把是0的地方都跳过就可以了,用矩阵保存前一个非0数的位置是多少.二师兄给我看了一个代码,人家根本没用别的优化,直接将最里层k的循环提到了最外层,然后就AC了,对此我表示无语. 1 #include <cstd

hdu6078[优化递推过程] 2017多校4

/*hdu6078[优化递推过程] 2017多校4*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; const LL MOD = 998244353LL; int T, m, n, a[2005], b[2005]; LL sum[2005][3], dp[2005][3]; void solve() { LL ans = 0; for (int i = 1; i <= n; i++) { LL

hdu 4686 矩阵乘法优化递推关系

这里有一份解题报告 解题报告 这是理论知识: 点我 最主要的是构造乘法矩阵,这个是通过递推关系得到的. 有了它,求数列的第n项可以在log(n)的时间里求出来. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <algorithm> 6 #include <map> 7 #include<vect

[BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j 位的字符串个数,然后转移就是可以从第 j 位加上一个字符转移到另一个位置. 然而..我并没有写过KMP + DP,我觉得还是写AC自动机+DP比较简单..于是,尽管只有一个模式串,我还是写了AC自动机+DP. 然后就是建出AC自动机,f[i][j] 表示长度为 i ,走到节点 j 的字符串的个数.

一道简单的递推题(快速幂+矩阵乘法优化+滚动数组)

问题 F: 一道简单的递推题 时间限制: 1 Sec  内存限制: 128 MB提交: 546  解决: 48[提交][状态][讨论版] 题目描述 存在如下递推式: F(n+1)=A1*F(n)+A2*F(n-1)+...+An*F(1) 求第K项的值对1000000007取模的结果 输入 单组测试数据 第一行输入两个整数 n , k (1<=n<=100,n<k<=10000000000) 第二行输入 n 个整数 F(1)   F(2)   ...   F(n) 第三行输入 n