なんでバカのブログを読みたいの!为什么要看菜鸟的博客!|

园龄:粉丝:关注:

矩阵快速幂 笔记

本文原在 2024-05-10 20:48 发布于本人洛谷博客。

一、简单介绍

一个 \(m\times n\) 的矩阵 \(A\) 可以和一个 \(n\times p\) 的矩阵 \(B\) 相乘,得到一个大小为 \(n\times p\) 的矩阵 \(C\),其中:

\[C_{i,j}=\sum_{k=1}^nA_{i,k}\times B_{k,j} \]

那么就可以用快速幂求矩阵幂了。

二、简单应用

1. P1962 斐波那契数列

\(f_1=f_2=1\)\(f_i=f_{i-1}+f_{i-2}\),求 \(f_n\bmod 10^9+7\)

我们假设矩阵 \(\begin{bmatrix}f_{i-1}&f_i\end{bmatrix}\) 乘上某一个矩阵之后可以得到 \(\begin{bmatrix}f_i&f_{i+1}\end{bmatrix}\),由于 \(f_i=0\times f_{i-1}+1\times f_i\)\(f_{i+1}=1\times f_{i-1}+1\times f_i\),所以:

\[\begin{bmatrix}f_{i-1}&f_i\end{bmatrix}\times\begin{bmatrix}0&1\\1&1\end{bmatrix}=\begin{bmatrix}f_i&f_{i+1}\end{bmatrix} \]

矩阵快速幂解决即可。

2. 数列

\(f_1=f_2=0\)\(f_i=7\times f_{i-1}+6\times f_{i-2}+4\times 3^i+5\times i\),求 \(f_n\bmod 10^9+7\)

同理,假设矩阵 \(\begin{bmatrix}f_{i-1}&f_i&4\times 3^i&5\times i&5\end{bmatrix}\) 乘上某一个矩阵可以得到 \(\begin{bmatrix}f_i&f_{i+1}&4\times 3^{i+1}&5\times (i+1)&5\end{bmatrix}\)

由于:

\[\left\{\begin{matrix} f_i&=&1\times f_i \\ f_{i+1}&=&6\times f_i+7\times f_{i-1}+3\times 4\times 3^i+1\times 5\times i+1\times 5 \\ 4\times 3^{i+1}&=&3\times 4\times 3^i \\ 5\times (i+1)&=&1\times 5\times i+1\times 5 \\ 5&=&1\times 5 \end{matrix}\right. \]

所以:

\[\begin{bmatrix}f_{i-1}&f_i&4\times 3^i&5\times i&5\end{bmatrix} \times \begin{bmatrix} 0 & 6 & 0 & 0 & 0\\ 1 & 7 & 0 & 0 & 0\\ 0 & 3 & 3 & 0 & 0\\ 0 & 1 & 0 & 1 & 0\\ 0 & 1 & 0 & 1 & 1 \end{bmatrix} = \begin{bmatrix}f_i&f_{i+1}&4\times 3^{i+1}&5\times (i+1)&5\end{bmatrix} \]

3. CF691E Xor-sequences

给定一个数集 \(A\),现在你需要构造一个长度为 \(k\) 的序列 \(B\),序列 \(B\) 的元素从数集 \(A\) 中任意挑选,要求 \(B\) 中任意相邻的两个数字的异或值二进制表示中 \(1\) 的个数是 \(3\) 的倍数,求方案数,对 \(10^9+7\) 取模。

\(1\le n\le 100\)\(1\le k,a_i\le 10^{18}\)

\(f_{i,j}\) 表示当 \(B\) 序列长度为 \(i\),且最后一个选 \(j\) 的方案数,\(p(x)\) 表示 \(x\) 在二进制下 \(1\) 的个数,则:

\[f_{i+1,j}=\sum_{k=1}^n f_{i,k}[3\mid p(a_j\oplus a_k)] \]

最终答案即为 \(\sum_{i=1}^n f_{n,i}\)

考虑优化,由于每一个 \(j\) 都只能从固定的某几个 \(k\) 转移而来(因为 \(a_j\oplus a_k\) 的值与 \(i\) 无关),所以考虑矩阵加速。

假设 \(\begin{bmatrix} f_{i,1} & f_{i,2} & f_{i,3} & \dots & f_{i,n} \end{bmatrix}\) 乘上某个矩阵可以得到 \(\begin{bmatrix} f_{i+1,1} & f_{i+1,2} & f_{i+1,3} & \dots & f_{i+1,n} \end{bmatrix}\)\(c(j,k)\) 表示 \(3\mid p(a_j\oplus a_k)\)。根据上面的状态转移方程,这是一个 \(n\times n\) 的矩阵,第 \(i\) 行第 \(j\) 列的值就是 \(c(i,j)\),写个函数即可。

matrix b(n, n, false);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) b.d[i][j] = check(a[i], a[j]);
b = pow_matrix(b, k - 1);
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) ans = (ans + b.d[i][j]) % mod;
cout << ans;

本文作者:Garbage fish's Blog

本文链接:https://www.cnblogs.com/Garbage-fish/p/18709908

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Garbage_fish  阅读(2)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起