矩阵的实质与线性代数有关,但用处并不大感兴趣的可以看看这里

这里我们重点探讨矩阵乘法,\(n \times m\) 阶的矩阵 \(A\) 乘以 \(m \times k\) 阶的矩阵 \(B\) 得到的矩阵 \(C\) 是 \(n \times k\) 阶的,且 \(C_{i,j}=\sum\limits_{k=1}^m A_{i,k}\times B_{k,j}\)。其矩阵乘法满足结合律,不满足交换律。

偶对了,矩阵乘法有个小技巧,卡常数时可以用,且大部分情况都适用,link

矩阵与线性递推

简单线性递推

定义 \(F_i\) 为斐波那契数列第 \(i\) 项,斐波那契数列定义如下

\[Fib_n = \left\{\begin{aligned} 1 \space (n \le 2) \\ Fib_{n-1}+Fib_{n-2} \space (n\ge 3) \end{aligned}\right.
\]

给定一个 \(n\),求出 \(Fib_n \bmod 10^9+7\) 的值。其中 \(n \le 10^9\)。

此题的一个经典做法是递推,时间复杂度为 \(O(n)\),当 \(n \le 10^9\) 时无法快速得到答案。而下面则会介绍一种能够在 \(O(\log n)\) 的时间复杂度内求解的办法。

定义一个矩阵 \(F_n=\left[\begin{matrix}
Fib_n&Fib_{n+1}\\
\end{matrix}
\right]\),我们希望对这个矩阵做一些操作使他从 \(F_n\) 变成 \(F_{n+1}\)。考虑构造一个矩阵 \(A=\left[\begin{matrix}
0&1\\
1&1
\end{matrix}
\right]\)。

我们就会发现

\[\begin{aligned}
F_n\times A&=\left[\begin{matrix}
Fib_n\times 0+Fib_{n+1}\times1&Fib_n\times 1+Fib_{n+1}\times 1\\
\end{matrix}
\right]\\
&=\left[\begin{matrix}
Fib_{n+1}&Fib_n+Fib_{n+1}\\
\end{matrix}
\right]\\
&=\left[\begin{matrix}
Fib_{n+1}&Fib_{n+2}\\
\end{matrix}
\right]\\
&=F_{n+1}
\end{aligned}\]

也就是说,\(F_n\times A\) 相当于往前递推一次为 \(F_{n+1}\),根据定义,我们让 \(F_0=\left[\begin{matrix}
0&1\\
\end{matrix}
\right]\),只要计算出 \(F_0\times A^n\),即往前递推 \(n\) 次就能得到 \(Fib_n\) 的值。由于矩阵满足结合律,可以和快速幂的技术相结合。因此 \(A^n\) 则可以通过快速幂来求解。这个问题就可以在 \(O(k^3\log n)\) 内求解。其中 \(k\) 是指我们构造的矩阵 \(A\) 是 \(k\times k\) 的,在本题中满足 \(k=2\),大部分题目的 \(k\) 不会很大。

构造矩阵的技巧:对于 \(A\times B=C\) 中的三个矩阵 \(A,B,C\),其中 \(A,C\) 均为 \(1\times k\) 的矩阵,而 \(B\) 是 \(k\times k\) 的转移矩阵,我们考虑 \(A\) 第 \(i\) 个位置为 \(B\) 第 \(j\) 个位置的贡献,并将贡献的系数填入 \(B_{i,j}\) 位置即可,具体可以参考上面的例题。

广义矩阵乘法

我们将矩阵乘法扩展到一般形式,即 \(C_{i,j}=\bigoplus\limits_{k=1}^n A_{i,k}\otimes B_{k,j}\),其中 \(\bigoplus,\bigotimes\) 是两种不同的运算符;我们希望扩展的矩阵乘法仍然满足结合律,则必须要求 \(\bigotimes\) 具有结合律,且 \(\bigotimes\) 对 \(\bigoplus\) 具有分配律,两种常见的广义矩阵乘法如 \(\max,+\) 和 \(\min,+\),借用这两种矩阵,可以完成更多的操作。

例题

P2044 [NOI2012] 随机数生成器

\(F_n=\left[\begin{matrix}
X_n&1
\end{matrix}
\right],A=\left[\begin{matrix}
a&c\\
0&1\\
\end{matrix}
\right],F_0=\left[\begin{matrix}
X_0&1
\end{matrix}
\right]\)

对于这种在递推中要加一个常数项的情况,在矩阵 \(F\) 中多加一维为 \(1\),然后 \(A\) 中加上一个系数,表示 \(+(1\times c)\)。

P2461 [SDOI2008] 递归数列

本题的目标是 \(\sum\limits_{i=m}^{n}{a_{i}}\),我们可以分别求出 \(\sum\limits_{i=1}^{m-1}a_i,\sum\limits_{i=1}^{n}a_i\) 的值,相减后再取模。问题就在于如何求出\(\sum\limits_{i=1}^{n}a_i\) 的值

我们另 \(S_n=\sum\limits_{i=1}^{n}a_i\),构建一个 \(1\times (k+1)\) 的矩阵 \(F\),其中 \(F_n=\left[\begin{matrix}
S_n&S_{n+1}&\dots&S_{n+k}
\end{matrix}
\right],F_0=\left[\begin{matrix}
0&b_1&b_1+b_2&\dots&\sum\limits_{i=1}^k b_i
\end{matrix}
\right]\)

矩阵 \(A\) 的前 \(k\) 行很好构建,\(A_{i,i+1}=1(i<=k)\),其他均为 \(0\),但是第 \(k+1\) 行却很难表示。

我们不妨思考一下,\(S_{n+k+1}\)如何表示

\[\begin{aligned}S_{n+k+1}&=S_{n+k}+a_{n+k+1}\\
&=S_{n,k}+\sum_{j=1}^{k}{c_{j} \times a_{n+k+1-j}}\\
&=S_{n,k}+\sum_{j=1}^{k}{c_{j} \times (S_{n+k+1-j}-S_{n+k-j})}\\
&=S_{n+k}+\sum_{j=1}^{k}(c_{j}\times S_{n+k+1-j}-c_j\times S_{n+k-j})\\
&=S_{n+k}\times(c_k+1)+\sum_{j=1}^{k-1}S_{n+k-j}\times(c_{k-j+1}-c_{k-j})-S_n\times c_k
\end{aligned}
\]

最后一步相当于把式子拆开,计算每一个 \(S\) 的系数,这样就可以购造出矩阵 \(A\) 的第 \(k+1\) 行

  1. \(A_{k+1,k+1}=c_1+1\)
  2. \(A_{k+1,1}=-c_k\)
  3. 对于剩下的 \(A_{k+1,i}\),\(A_{k+1,i}=c_{k-i+2}-c_{k-i+1}\)

按照上述思路,就可以写出矩阵 \(A\)。

\[\left[
\begin{matrix}
0&1&0&\dots&0\\
0&0&1&\dots&0\\
\vdots&\vdots&\vdots&\ddots&\vdots\\
0&0&0&\dots&1\\
-c_k&c_k-c_{k-1}&c_{k-1}-c_{k-2}&\dots&c_1+1
\end{matrix}
\right]\]

直接乘就行了。

P2579 [ZJOI2005] 沼泽鳄鱼

注意到 \(T\) 的取值只有 \(2,3,4\)。这说明每过 \(12\) 秒所有食人鱼会从起点重新开始,而这十二秒每一秒对应的矩阵都不一样,需要单独构造。

构造完成后,求出 \(F_0\times A^{12\left\lfloor\frac{n}{12}\right\rfloor}\times A^{n\bmod 12}\) 即可得到答案,前者将 \(12\) 个矩阵乘起来用快速幂算,后者直接推着算就行。

AT_dp_r Walk

设 \(f_{k,i,j}\) 表示从 \(i\) 出发,到 \(j\),走过 \(k\) 条边的方案数。\(w_{i,j}\) 表示 \(i\to j\) 这条边是否存在。

我们思考上一步走的是哪个点,可列出转移方程:

\[f_{k,i,j}=\sum_{l=1}^nf_{k-1,i,l}\times w_{l,j}
\]

容易发现 \(K\le 10^{18}\),稳稳超时。

观察转移方程,诶!这个转移怎么和矩阵乘法这么像:

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

我们设矩阵 \(F_k\) 的大小为 \(n\times n\),其中这个矩阵第 \(i\) 行第 \(j\) 列表示 \(f_{k,i,j}\),设矩阵 \(A\) 大小同样为 \(n\times n\),其中这个矩阵第 \(i\) 行第 \(j\) 列表示 \(w_{i,j}\)。则显然:\(F_{k}\times A=F_{k+1}\),由转移方程可知。

\(F_0\) 为左上右下对角线为 \(1\),其余均为 \(0\) 的单位矩阵,则递推的目标状态 \(F_{K}\) 可以表示为:

\[F_0\times A^K
\]

时间复杂度 \(O(n^3\log K)\),其中 \(O(n^3)\) 是一次矩阵乘法的复杂度。

好像 \(F\) 矩阵也可以设计成一维的,设计成二维就是为了图个方便。

P2886 [USACO07NOV] Cow Relays G

和上一题很像,不过这一题要求经过 \(K\) 条边的最短路径。

考虑 Floyd 算法,其本质也是动态规划,设 \(f_{k,i,j}\) 表示从 \(i\) 出发,到 \(j\),走过 \(k\) 条边的最短路径。\(w_{i,j}\) 表示 \(i\to j\) 这条边的边权。

\[f_{k,i,j}=\min_{l=1}^n f_{k-1,i,l}+ w_{l,j}
\]

不难发现这和上一题的唯一区别是 \(+\) 变 \(\min\),\(\times\) 变 \(+\),直接用广义矩阵乘法计算即可。

推荐的题目

P6190 [NOI Online #1 入门组] 魔法

P6569 [NOI Online #3 提高组] 魔法值

P1357 花园

P5175 数列

矩阵与 ddp

在上一个部分中,已经出现了矩阵优化 dp 的部分。启示我们可以通过矩阵实现快速的转移,而通过广义矩阵乘法和数据结构,可以把一些简单的 dp 转移方程写成矩阵的形式。用这些矩阵的乘积完成修改和 dp 快速转移,这种 dp 就叫做动态 dp,也叫做 ddp。

线段树维护矩阵乘积

这个东西貌似还不是动态 dp,不过我还是认为其本质是 ddp。

例题:SPOJ1716 GSS3 - Can you answer these queries III

经典带修区间最大子段和,这里使用 ddp。

先思考不带修的,且查询范围为 \([1,n]\) 的做法。

设 \(f_i\) 表示以 \(i\) 结尾的最大子段和,\(g_i\) 表示 \(1\sim i\) 中的最大子段和。可以列出转移方程:

\[f_i=\max(f_{i-1}+a_i,a_i)
\]
\[g_i=\max(g_{i-1},f_i)
\]

这里 \(g_i\) 看上去没什么有,主要是下文在 ddp 中统计答案比较方便。定义矩阵 \(F_{i}=\left[\begin{matrix}f_i&g_i\end{matrix}\right]\),我们思考如何确定一个矩阵 \(A_i\) 使得 \(F_{i-1}\times A_i=F_i\)。

用上上文所说的广义矩阵乘法,显然 \(F\times A\) 用的是 \(\max,+\) 乘法。根据定义,我们逐步分析:

\(f_{i+1}=\max(f_i+A_{1,1},g_i+A_{2,1})\)

显然 \(f_i\gets a_i\) 这种转移方式没有考虑到,我们在 \(F\) 矩阵中加上一维 \(0\),则:

  • \(f_{i+1}=\max(f_i+A_{1,1},g_i+A_{2,1},0+A_{3,1})\):根据上文,可将 \(A_{1,1}=a_i,A_{2,1}=-\infty,A_{3,1}=a_i\)。

  • \(g_{i+1}=\max(f_i+A_{1,2},g_i+A_{2,2},0+A_{3,2})\):我们还没有算出 \(f_{i+1}\),不过可以上面的方式表示出 \(f_{i+1}\)。可将 \(A_{1,2}=a_i,A_{2,2}=0,A_{1,3}=a_i\),即符合题意。

  • \(0=\max(f_i+A_{1,3},g_i+A_{2,3},0+A_{3,3})\),为了放置一些其他的东西破坏 \(0\),可将 \(A_{1,3}=A_{2,3}=-\infty,A_{3,3}=0\)。

综上,我们得到两个矩阵:

\[F_i=\left[\begin{matrix}f_i&g_i&0\end{matrix}\right],A_i=\left[\begin{matrix}a_i&a_i&-\infty\\-\infty&0&-\infty\\a_i&a_i&0\end{matrix}\right]
\]

此时,$$F_i\times A_{i+1}=F_{i+1}$$。我们初始 \(F_0=\left[\begin{matrix}0&0&0\end{matrix}\right]\),此时 \(F_{n}=F_0\times \prod_{i=1}^nA_i\)。我们就可以用矩阵乘法完成 dp 转移。答案即为 \(F_n\) 中 \(g_i\) 的值。

实际上,在 \([l,r]\) 这一段区间内做 dp,实际上就是计算 \(F'=F_0\times \prod_{i=l}^rA_i\),这样答案就是 \(F'\) 中的 \(g_i\)。我们要做的就是快速求出 \(\prod_{i=l}^rA_i\)。显然可以利用线段树维护矩阵乘积,即可做到时间复杂度 \(O(k^3\log n)\),其中 \(k=3\),表示矩阵大小。

对于修改操作,我们只需要修改一个矩阵的值即可,这样,这道题就变成了一个支持单点修改矩阵,求区间矩阵积的线段树模板。时间复杂度 \(O(k^3n\log n)\),\(k=3\)。

代码就不放了(实际上这题的 ddp 做法都是口胡的)。

倍增维护矩阵乘积

对于树上的一些静态不待修路径问题,可以用倍增维护矩阵乘积实现 ddp。

例题:P7359 「JZOI-1」旅行

注意到 dp 的转移从序列到了树上,实际上还是一样的,我们按照两点之间路径的顺序转移即可。容易发现在每个节点处的状态无疑有两种:有船或没船。dp 的转移也有两种顺序,深度从下到上或从上到下。设 \(f_{u,1/0}\) 表示从起点出发,一直往上走到 \(u\) 有/没船的最小花费。\(g_{u,1/0}\) 表示从 \(u\) 走到终点,在 \(u\) 点有/没船的最小花费。

记 \(u\) 为 \(v\) 的父亲,\(a_i\) 为从 \(u,v\) 之间往来的时间,\(z_i\) 为从 \(u\) 到 \(v\) 节省的时间,如果从有船变没船,则现在起点把船砸了再出发,可以列出方程:

\[f_{u,0}=\min(f_{v,0}+a_i,f_{v,1}+a_i)
\]
\[f_{u,1}=\min(f_{v,0}+a_i+z_i+L,f_{v,1}+a_i+z_i)
\]
\[g_{v,0}=\min(g_{u,0}+a_i,g_{u,1}+a_i)
\]
\[g_{v,1}=\min(g_{u,0}+a_i-z_i+L,g_{u,1}+a_i-z_i)
\]

我们思考如何用矩阵刻画 dp 的转移,注意每个节点只有一个父亲,所以定义矩阵 \(F_v\) 表示乘上这个矩阵相当于从 \(v\) 转移到 \(u\),矩阵 \(G_v\) 表示乘上这个矩阵为从 \(u\) 转移到 \(v\)。注意这里转移的顺序是不一样的。则:

\[\left[\begin{matrix}f_{v,0}&f_{v,1}\end{matrix}\right]\times \left[\begin{matrix}a_i&a_i+z_i+L\\a_i&a_i+z_i\end{matrix}\right]=\left[\begin{matrix}f_{u,0}&f_{u,1}\end{matrix}\right]
\]
\[\left[\begin{matrix}g_{u,0}&g_{u,1}\end{matrix}\right]\times
\left[\begin{matrix}a_i&a_i-z_i+L\\a_i&a_i-z_i\end{matrix}\right]=\left[\begin{matrix}g_{v,0}&g_{v,1}\end{matrix}\right]\]

对于从 \(s\) 到 \(t\) 的 dp,我们记 \(l\) 为 \(s,t\) 的最近公共祖先,则我们先把 \(s\to l\) 路径上的所有矩阵(不包含 \(l\))乘起来,再把 \(l\to t\) 路径上的矩阵(不包含 \(l\))乘起来。可以用倍增优化。注意:矩阵不满足交换律,所以乘的时候一定要按照顺序

时间复杂度 \(O(k^3(n+q)\log n)\)。

动态 dp

终于要开始写模板题了!

模版题:P4719【模板】动态 DP

首先,树上最大权独立集的朴素 dp 如下:

\[f_{u,0}=\sum_{v\in \text{son}(x)}\max(f_{v,0}+f_{v,1})
\]
\[f_{u,1}=a_u+\sum_{v\in \text{son}(x)}f_{v,0}
\]

其中,\(f_{u,1/0}\) 表示 \(u\) 选择或不选择。然后就面临了第一个难题:每个节点的儿子数可能很多,这会导致矩阵的规模过大,无法承受。不过我们发现:如果这样存储,修改可以只用修改一个位置的矩阵,显然不够平衡。

这里用到一个很牛的技巧,我们利用树链剖分将儿子划分成轻儿子和重儿子,记 \(u\) 的重儿子为 \(s_u\),定义数组 \(g_{u,1/0}\) 表示选择或不选择 \(u\) 且只从轻儿子转移,我们更改转移的方程:

\[g_{u,0}=\sum_{v\in \text{son}(u),v\ne s_u}\max(f_{v,0},f_{v,1})
\]
\[g_{u,0}=a_u+\sum_{v\in \text{son}(u),v\ne s_u}f_{v,0}
\]
\[f_{u,0}=g_{u,0}+\max(f_{s_u,0},f_{s_u,1})
\]
\[f_{u,1}=g_{u,1}+f_{s_u,0}
\]

我们在每个节点上存储矩阵 \(G\),表示乘上这个矩阵 \(G_u\) 代表从 \(s_u\) 转移到 \(u\),矩阵的运算为 \(\max,+\)。则

\[\left[\begin{matrix}f_{s_u,0}&f_{s_u,1}\end{matrix}\right]\times
\left[\begin{matrix}g_{u,0}&g_{u,1}\\g_{u,0}&-\infty\end{matrix}\right]=\left[\begin{matrix}f_{u,0}&f_{u,1}\end{matrix}\right]\]

我们在维护每个点 \(u\) 所在链的链顶 \(top_u\) 的情况下维护每个点所在链的链顶 \(ed_u\),则整颗树的最大独立集就是从 \(ed_1\) 到 \(1\) 的路径上,按照从下倒上的顺序的矩阵的乘积。

那修改操作呢?我们发现在转移的过程中,如果 \(u\) 是 \(v\) 的重儿子,则 \(v\) 顶点上的矩阵不用做任何修改;但如果 \(u\) 是 \(v\) 的轻儿子,则需要修改 \(v\) 上的矩阵。所以我们不断跳到当前重链的顶端,并修改链顶父亲的矩阵 \(G\),再跳到链顶父亲;直到跳过了 \(1\) 号点。

因为一个点从本节点跳到根节点经过的轻边数不超过 \(\log n\) 条,所以我们至多修改 \(\log n\) 个矩阵。这样时间复杂度就控制在一个正确的范围内。

如何更新链顶父亲的矩阵?注意各个轻儿子对链顶父亲个贡献是独立的,也就是说,我们可以减掉链顶对于链顶父亲原本的贡献,更新后,再把链顶对链顶父亲的新贡献加回去。这样就可以做到快速修改了。

在进行单点修改时,尽量不要再参数中传入矩阵,可以用额外的数组辅助。record,时间复杂度 \(O(k^3(n+q)\log n)\)。

例题

CF705E New Year and Old Subsequence

我们还是先思考对于序列 \([1,n]\) 普通 dp 做法。

设 \(dp_{0/1/2/3/4}\) 表示使子序列仅包含 \(\varnothing/2/20/201/2017\) 所需的最小修改次数。dp 和核心思路是,如果不是关键字符留着不删,要么删除当前字符继承上一阶段的 dp 值,要么在一定条件下向子序列末尾加入一个新字符。举个例子:

\[dp_{i,0}=dp_{i-1,0}+[s_i\ne 2]
\]
\[dp_{i,1}=\min(dp_{i-1,1}+[s_i=0],dp_{i-1,0}+[s_i\ne 2]\infty)
\]
\[dp_{i,2}=\min(dp_{i-1,2}+[s_i=1],dp_{i-1,1}+[s_i\ne 0]\infty)
\]
\[dp_{i,3}=\min(dp_{i-1,3}+[s_i=6]+[s_i=7],dp_{i-1,2}+[s_i\ne 1]\infty)
\]
\[dp_{i,4}=\min(dp_{i-1,4}+[s_i=6],dp_{i-1,3}+[s_i\ne 7]\infty)
\]

然后使用 \(\min,+\) 矩阵进行转移,区间做 dp 就是求区间矩阵乘积,可以用线段树维护。

注意到矩阵的大小是 \(5\times 5\) 的,所以直接算出来矩阵乘积的常数是相当巨大的 \(5^3\),详细参见这篇文章,我们传入一个初始为 \(1\times 5\) 的矩阵,然后直接乘起来,常数就降到是 \(5^2\)。

详细参见代码,record

时间复杂度 \(O(k^3n+k^2q\log n)\),其中 \(k=5\)。

P6021 洪水

感觉这个才是味道最重的 ddp。

设 \(f_u\) 表示将 \(u\) 到子树内叶子节点全部阻断的最小花费。普通 dp 转移:

\[f_u=\min\left(\sum_{v\in\text{son}(u)}f_v,a_u\right)
\]

划分轻重儿子,定义 \(u\) 的重儿子为 \(s_u\)。则:

\[g_u=\sum_{v\in\text{son}(u),v\ne s_u}f_v
\]
\[f_u=\min(g_u+f_{s_u},a_u)
\]

注意到更带修最大子段和那题较像,我们手动增加一维 \(0\)。则

\[\left[\begin{matrix}f_{s_u}&0\end{matrix}\right]\times
\left[\begin{matrix}g_u&\infty\\a_u&0\end{matrix}\right]=\left[\begin{matrix}f_u&0\end{matrix}\right]\]

这里的乘法是 \(\min,+\) 乘法,套用上面的套路即可 AC。时间复杂度 \(O(k^3(n+q)\log n)\)。

因为蒟蒻太唐了所以只会写简单题,以后会加复杂的例题的(确信)。

矩阵与 DS

额,突然想起来这个东西了,貌似借助懒标记和广义矩阵乘法能实现上 DS 中难以刻画的操作?

例题:P4314 CPU 监控

此题的经典做法是维护历史和和加法标记的当前值和历史最值,然后直接信息下传与合并,具有一定的思维性,而借助矩阵就可以无脑草过去,代价则是较大的常数。

在每个节点上,维护矩阵 \(\left[\begin{matrix}s&hs\end{matrix}\right]\),分别表示当前区间最大值和当前区间历史最大值。利用 \(\max,+\) 矩阵乘法刻画各个操作。

对于区间加法,我们给每个位置都乘上一个矩阵 \(A=\left[\begin{matrix}v&v\\-\infty&0 \end{matrix}\right]\)

区间赋值操作,我们希望表示成 \(a_i\gets \max\{a_i-\infty,v_i+0\}\) 的形式,所以每个节点上的矩阵还有加一维,变成 \(\left[\begin{matrix}s&hs&0\end{matrix}\right]\),改变定义后加法矩阵和赋值矩阵分别表示为:

\[\left[\begin{matrix}v&v&-\infty\\-\infty&0&-\infty\\-\infty&-\infty&0\end{matrix}\right],\left[\begin{matrix}-\infty&-\infty&-\infty\\-\infty&0&-\infty\\v&v&0\end{matrix}\right]
\]

因为矩阵乘法满足结合律,只需要按顺序打上标记下传即可,时间复杂度 \(O(k^3n\log n)\)。

The End

文章标题灵盖来源于溜冰

矩阵与 dp 与线性递推的更多相关文章

  1. 矩阵乘法&矩阵快速幂&矩阵快速幂解决线性递推式

    矩阵乘法,顾名思义矩阵与矩阵相乘, 两矩阵可相乘的前提:第一个矩阵的行与第二个矩阵的列相等 相乘原则: a b     *     A B   =   a*A+b*C  a*c+b*D c d     ...

  2. HDU 5863 cjj's string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )

    题目链接 题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数 分析 : 直觉是DP 不过当时看到 n 很大.但 ...

  3. 2018 焦作网络赛 L Poor God Water ( AC自动机构造矩阵、BM求线性递推、手动构造矩阵、矩阵快速幂 )

    题目链接 题意 : 实际上可以转化一下题意 要求求出用三个不同元素的字符集例如 { 'A' .'B' .'C' } 构造出长度为 n 且不包含 AAA.BBB CCC.ACB BCA.CAC CBC ...

  4. 利用Cayley-Hamilton theorem 优化矩阵线性递推

    平时有关线性递推的题,很多都可以利用矩阵乘法来解决. 时间复杂度一般是O(K3logn)因此对矩阵的规模限制比较大. 下面介绍一种利用利用Cayley-Hamilton theorem加速矩阵乘法的方 ...

  5. [NOI2017]泳池——概率DP+线性递推

    [NOI2017]泳池 实在没有思路啊~~~ luogu题解 1.差分,转化成至多k的概率减去至多k-1的概率.这样就不用记录“有没有出现k”这个信息了 2.n是1e9,感觉要递推然后利用数列的加速技 ...

  6. AcWing 226. 233矩阵 (矩阵快速幂+线性递推)打卡

    题目:https://www.acwing.com/problem/content/228/ 题意:有一个二维矩阵,这里只给你第一行和第一列,要你求出f[n][m],关系式有    1,  f[0][ ...

  7. HDU - 6172:Array Challenge (BM线性递推)

    题意:给出,三个函数,h,b,a,然后T次询问,每次给出n,求sqrt(an); 思路:不会推,但是感觉a应该是线性的,这个时候我们就可以用BM线性递推,自己求出前几项,然后放到模板里,就可以求了. ...

  8. BM求线性递推模板(杜教版)

    BM求线性递推模板(杜教版) BM求线性递推是最近了解到的一个黑科技 如果一个数列.其能够通过线性递推而来 例如使用矩阵快速幂优化的 DP 大概都可以丢进去 则使用 BM 即可得到任意 N 项的数列元 ...

  9. [JZOJ6088] [BZOJ5376] [loj #2463]【2018集训队互测Day 1】完美的旅行【线性递推】【多项式】【FWT】

    Description Solution 我们考虑将问题一步步拆解 第一步求出\(F_{S,i}\)表示一次旅行按位与的值为S,走了i步的方案数. 第二步答案是\(F_{S,i}\)的二维重复卷积,记 ...

  10. CH定理与线性递推

    才发觉自己数学差的要死,而且脑子有点浑浑噩噩的,学了一个晚上才学会 如果说的有什么不对的可以在下面嘲讽曲明 以下无特殊说明时,默认方阵定义在实数域上,用\(|A|\)表示\(A\)的行列式 特征值与特 ...

随机推荐

  1. 康谋产品 | 用于ADAS和AD传感器的独立数据采集设备

    一.产品简介 在 ADAS/AD 环境中,如果想要将原始数据与摄像头.雷达或激光雷达等传感器分离,总是会使用测量数据转换器.借助MDILink,您可以获得一个SerDes测量数据转换器,从开发阶段和验 ...

  2. EFCore Study(3)——“一”对多关系的设定和插入、查找级联操作

    一.建立文章.评论类 /// <summary> /// 文章 /// </summary> public class Artitle { public int Id { ge ...

  3. python中_自动生成的_pycache__文件夹

    _pycache__文件夹可以看作该文件夹下文件已被python接管或者说编译过. 在第一次执行代码的时候,Python解释器已经把编译的字节码放在__pycache__文件夹中,这样以后再次运行的话 ...

  4. FastAPI与Tortoise-ORM模型配置及aerich迁移工具

    title: FastAPI与Tortoise-ORM模型配置及aerich迁移工具 date: 2025/04/30 00:11:45 updated: 2025/04/30 00:11:45 au ...

  5. 【工具】浏览器插件|Edge浏览器划词翻译插件(可用于翻译PDF文件,截图翻译)

    本文体验版本:Edge v10.1.0 偶然安装了一个国人自13年开发至今的划词翻译浏览器插件,曾经开源,现在闭源. 功能全面到令人落泪. 全面到反手把小绿鲸扔了-- 官方介绍是支持一站式划词 / 截 ...

  6. 阿里云Ansible自动化运维平台部署

    以下是在阿里云平台上基于Ansible实现自动化运维的完整实践指南,整合所有核心操作流程和命令,适配指定的服务器规划: 一.环境规划 主机名 IP地址 角色 操作系统 manage01 192.168 ...

  7. 鸿蒙NEXT开发教程:浅谈@ComponentV2装饰器

    听说今天的广州车展上有一部分人已经看到华为汽车的最后一"界",尊界超豪华大轿车,应该很快就要正式亮相,可以期待一波. 在api12之后,鸿蒙系统推出一个V2版本的状态管理装饰器,不 ...

  8. RISC-V指令精讲(一):算术指令--加法指令、比较指令

    本节来看下RV32I(32位整数指令集)的算数指令,先学习下加减指令(add.sub),接着了解下数值比较指令(slt),这些指令都有两个版本:一个是立即数版本,一个是寄存器版本 RISCV-V指令格 ...

  9. 通过tushare获取k线数据

    tushare中get_k_date接口主要目的是获取k线数据,该接口融合了get_hist_data和get_h_data两个接口的功能,即能方便获取日周月的低频数据,也可以获取5.15.30和60 ...

  10. C#之MethodImpl(MethodImplOptions.Synchronized)

    [MethodImpl(MethodImplOptions.Synchronized)] 是 C# 中用于指定方法同步的一个特性,它控制方法的执行方式,确保在多线程环境下某个方法的执行是线程安全的.它 ...