矩阵乘法与动态 DP 入门

洛谷:https://www.luogu.com.cn/blog/ningago-lsh/ju-zhen-sheng-fa-yu-dong-tai-dp-ru-men

矩阵乘法及广义矩阵乘法

前置知识:矩阵相关基础概念。
A(i,j) 表示矩阵 A 的第 i 行第 j 列, nAA 的行数, mAA 的列数。
定义矩阵加法 A+B 为( nA=nB,mA=mB):

     [A+B](i,j)=A(i,j)+B(i,j)

矩阵加法有交换律,结合律。
定义矩阵乘法 A×B 为( mA=nB):

     [A×B](i,j)=k=1mA(Ai,k×Bk,j)

矩阵乘法满足结合律,对矩阵加法的分配律,但不满足交换律。
定义关于运算 (,) 广义矩阵乘法 A×B 为( mA=nB):

     [A×B](i,j)=k=1mA(Ai,kBk,j)

若其存在结合律,则:

     (AB)C=A(BC)k=1mB(p=1mA(A(i,p)B(p,k))C(k,j))=k=1mA(A(i,k)p=1mB(B(k,p)C(p,j)))

若:

  • 有(左、右)分配律;
  • 有结合律;
  • 有交换律。
    则有:

     k=1mBp=1mA(A(i,p)B(p,k)C(k,j))=k=1mAp=1mB(A(i,k)B(k,p)C(p,j))k=1mBp=1mA(A(i,p)B(p,k)C(k,j))=p=1mBk=1mA(A(i,k)B(k,p)C(p,j))

即满足结合律。
常见的 (,) 组合有: (+,×)(max,+)


练习题目:

  • B2104 矩阵加法
  • B3615 测测你的矩阵乘法
  • P3390 【模板】矩阵快速幂

矩阵递推

矩阵可以有效地解决线性组合问题。

斐波那契问题fibk=fibk1+fibk2,求 fibn

我们构造矩阵 fk1=[fibk1fibk2](注意下标)。

fk=fk1×[1110]

这样我们就可以用另一种方式 O(23n) 递推出 fibn

注意到这样递推每一项的转移都是一样的,而又知道矩阵有结合律,故 fk=f1×[1110]k1

矩阵显然可以使用快速幂,故可以 O(23logn) 递推出 fibn


那么,现在你已经对矩阵递推有一定的了解了,就让我们看一看下面这个简单的例子,来把我们刚刚学到的知识运用到实践中吧!

试试看!例题1.7

洛谷 P1707 刷题比赛

1 天 A,B,C 都做了 1 道题。第 2 天 A,B,C 都做了 3 道题。

A 同学第 k+2 天刷题数量 ak+2=pak+1+qak+bk+1+ck+1+rk2+tk+1

B 同学第 k+2 天刷题数量 bk+2=ubk+1+vbk+ak+1+ck+1+wk

C 同学第 k+2 天刷题数量 ck+2=xck+1+yck+ak+1+bk+1+zk+k+2

给定 n1016 和其它常数,求出 an,bn,cn,答案取模。

构造矩阵 fk1=[ak1,ak2,bk1,bk2,ck1,ck2,k2,(k2)2,1,wk2,zk2]

则有:fk=fk1×[p1101000000q000000000010u1100000000v000000001010x1000000000y000000t0001012000r000000100010002011100001000000w00000100000z]

fk=f2×Bk2B 是转移的矩阵)。
对矩阵进行快速幂即可 O(113logn) 解决。

https://www.luogu.com.cn/paste/u9m7bjru


总结:矩阵递推可以做的有:

  • 需要加前 t 项的 dp 值(乘系数),每个函数消耗 t 个矩阵空位。
  • 需要加常数,消耗 1 空位。
  • 需要加下标(±Δ),消耗 1 空位。
  • 需要加常数的下标(±Δ)次方,消耗 1 空位。
  • 需要加下标(±Δ)的 t 次方,消耗 t+1 空位(利用二项式定理)。

其中 Δ 需恒定。以上空位的消耗会有重叠。

练习题目:

  • P1939 【模板】矩阵加速(数列)
  • P1349 广义斐波那契数列
  • P3758 [TJOI2017]可乐
  • P2109 [NOI2007] 生成树计数

运用矩阵解决线性组合问题

P3373 【模板】线段树 2
区间加,区间乘,区间求和, n,m105

使用线段树维护。普通的懒标记太麻烦了,故使用矩阵求解。
构造一个节点的矩阵 fk=[valrl+1] ,则 fk=flson+frson

构造一个节点的懒标记矩阵 lazyk,初始 =[1001] 即单位元。

则对于区间加 z 操作,则对于需要操作的节点, lazyk×[1z10],fk×[1z10]

对于区间乘 z 操作,则对于需要操作的节点, lazyy×[z010],fy×[z010]

下放时设置 fson×lazyk,lazyson×lazyk 即可,和普通线段树大体没有区别。

至此我们可以使用 23 的常数解决原来复杂的懒标记下传(把矩阵乘法循环展开就和原来常数差不多了qwq)。

https://www.luogu.com.cn/paste/ulndkmq8


接下来本质理解一下这种做法。

U226931 Linear function?(原创题,可提交,不卡常(?))

n 节点的树,每个节点有 xi,yi,zi> 三个权值。

操作 1:对于所有 s,t 路径上的节点,xiaxi+byi+czi+d

操作 2:对于所有 s,t 路径上的节点,yiaxi+byi+czi+d

操作 3:对于所有 s,t 路径上的节点,ziaxi+byi+czi+d

操作 4:求出 s,t 路径上 xi+yi+zi 之和。

n,m105,答案取模,abcd0

操作 5 不是此题重点,可以用操作树实现,在此不赘述。

树上路径问题可以使用树链剖分或 LCT 实现。接下来仅讨论序列区间问题。

还是使用懒标记线段树。构造叶节点的矩阵:fk=[xkykzk1]。(1 的设置用来辅助常数即 d,参考例题 1.7)。

那么非叶节点的矩阵就为 fk=flson+frson=[xyzrl+1]

操作 1 相当于对 flazy[a000b100c010d001]

其它操作可以类似构造,即 [1a000b000c100d01][10a001b000c000d1]

复杂度 O(43mlogn)(LCT)。

https://www.luogu.com.cn/paste/yfwxrpuw

https://www.luogu.com.cn/paste/y9rc9urr


练习题目:

  • P7453 [THUSCH2017] 大魔法师

动态 DP

P4719 【模板】"动态 DP"&动态树分治

n 个节点的点权树,单点修改,求最大权独立集。

n,m105

考虑没有上司的舞会的做法。

fk,0,fk,1 表示只关心 k 节点的子树,k 节点选不选的方案数;

容易得到 fk,0=nxmax{fnx,0,fnx,1},fk,1=ak+nxfnx,0

为了方便修改,我们对树进行实链剖分(LCT 维护)。

gk,0,gk,1 表示 fk,0,fk,1 的递推式中,虚儿子和自身权值产生的贡献。

gk,0=nxhsonmax{fnx,0,fnx,1},gk,1=ak+nxhsonfnx,0

则我们可以用 (max,+) 广义矩阵乘法描述转移:

[fk,0fk,1]=[gk,0gk,0gk,1]×[fhson,0fhson,1]

注意叶节点的 hson 权值被定义为 Mleaf=[00]

为什么使用竖向量?

因为要适应 Splay 中 lsonkrson 的前序遍历关系。

显然在实链结构不改变的情况下,g 是不会改变的。

如何修改?(ax=y

Fk 表示 k辅助树上子树的矩阵积,即 Fk=Flson×[gk,0gk,0gk,1]×Frson

如果把 x access 到根,然后旋到辅助树根,此时没有一个节点的儿子是 x,就可以之间修改 xg

所以这启发我们维护 access 过程。

access 中,需要修改实儿子。这需要向 g 中添加权值或删除权值。这对于此题的求和式是简单的。

如何查询?

把原树根旋转为辅助树的根,即可得出 DP 值为 Froot×Mleaf

至此我们通过 O(nlogn) 的复杂度解决此题。

https://www.luogu.com.cn/paste/h8cx9ldw


可以总结出使用动态 DP 的前提条件:

  • 可以用广义矩阵乘法刻画虚儿子的贡献和实儿子的贡献。
  • 在插入一个新虚儿子或删除原有的一个虚儿子时可以快速更新 g
  • 更改权值后可以快速更新 g

注意不要把“快速”局限为 O(1)


P3781 [SDOI2017]切树游戏

n 个节点的带权树。

操作 1:单点修改权值。

操作 2:求有多少个非空联通子树,满足树内权值异或和为 t

n,m3×104,a,t128,t 不固定。答案取模。

容易发现这是个异或卷积,故令 Ai=FWT(xai)

One=FWT(1)

先考虑朴素 dp:fk 表示 k 的子树内,选了 k 的方案数,Fk 表示可以不选 k 的方案数。(两个都是 FWT 序列)

fk=Ak×nx(One+fnx),Fk=fk+nxFnx

实链剖分。

gk=Ak×nxhson(One+fnx),Gk=nxhsonFnx

(+,×) 的矩阵乘法刻画(gk×(One+fhson)=gk+gk×fhson):

[Fkfk1]=[0gkgk1gkgk+Gk001]×[Fhsonfhson1]

利用动态 DP 的基本方法即可。由于模数小,可以 O(1) 实现模意义除法。

由于除法可能有 0,所以对每个节点需要记录 cntk 表示现在的虚儿子中有多少个为 0

需要意识到动态 DP 的虚实儿子转化不是任意加减(乘除或其它),而是插入删除,这会带来很多良好的性质。接下来这题将会体现。

https://www.luogu.com.cn/paste/8rm5r98l


BZOJ5210 最大连通子块和

n 个节点的带权有根树。

操作 1:单点修改权值。

操作 2:求 x 的子树中最大的联通子块的点权和。

n,m2×105,点权有正有负。

fk 表示 k 的子树内,选了 k 的最大值,Fk 表示可以不选 k 的最大值。

fk=ak+nxmax{fk,0},Fk=max{0,fk,maxnx{Fnx}}

gk=ak+nxhsonmax{fk,0},Gk=max{0,maxnxhson{Fnx}}

利用 (max,+) 的广义矩阵乘法:

[Fkfk0]=[0gkGkgk00]×[Fhsonfhson0]

利用动态 DP 的基本方法,现在的问题是:Gmax 形式,怎么进行更改?

利用插删虚儿子的性质,对每个节点开一个可删堆维护即可。

怎么查询子树的答案?

x 旋到根,只保留自身和右儿子的矩阵合并即可。

复杂度 O(nlog2n)

https://www.luogu.com.cn/paste/boz9uo5g


练习题目:

  • P5024 [NOIP2018 提高组] 保卫王国
  • P8820 [CSP-S 2022] 数据传输
  • P6021 洪水

谢谢观看。

posted @   ningago  阅读(214)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示