Unverified Commit ed2c03c3 authored by Sshwy's avatar Sshwy Committed by GitHub
Browse files

Merge pull request #1531 from Chaigidel/master

新增矩阵例题
parents 799ecd84 56de9f03
Loading
Loading
Loading
Loading
+143 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ $$

#### 优化

首先对于比较小的矩阵,可以考虑直接手动展开循环以减小常数。

可以重新排列循环以提高空间局部性,这样的优化不会改变矩阵乘法的时间复杂度,但是会在得到常数级别的提升。

```cpp
@@ -179,6 +181,147 @@ int main() {
}
```

* * *

这是一个稍微复杂一些的例子。

$$
f_{1} = f_{2} = 0\\
f_{n} = 7f_{n-1}+6f_{n-2}+5n+4\times 3^n
$$

我们发现, $f_n$ 和 $f_{n-1}, f_{n-2}, n$ 有关,于是考虑构造一个矩阵描述状态。

但是发现如果矩阵仅有这三个元素 $\begin{bmatrix}f_n& f_{n-1}& n\end{bmatrix}$ 是难以构造出转移方程的,因为乘方运算和 $+1$ 无法用矩阵描述。

于是考虑构造一个更大的矩阵。

$$
\begin{bmatrix}f_n& f_{n-1}& n& 3^n & 1\end{bmatrix}
$$

我们希望构造一个递推矩阵可以转移到

$$
\begin{bmatrix}
f_{n+1}& f_{n}& n+1& 3^{n+1} & 1
\end{bmatrix}
$$

转移矩阵即为

$$
\begin{bmatrix}
7 & 1 & 0 & 0 & 0\\
6 & 0 & 0 & 0 & 0\\
5 & 0 & 1 & 0 & 0\\
4 & 0 & 0 & 3 & 0\\
0 & 0 & 1 & 0 & 1
\end{bmatrix}
$$

### 矩阵表达修改

???+note "「THUSCH 2017」大魔法师"
    ~~中二病患者~~大魔法师小 L 制作了 $n$ 个魔力水晶球,每个水晶球有水、火、土三个属性的能量值。小 L 把这 $n$ 个水晶球在地上从前向后排成一行,然后开始今天的魔法表演。

    我们用 $A_i,\ B_i,\ C_i$ 分别表示从前向后第 $i$ 个水晶球(下标从 $1$ 开始)的水、火、土的能量值。

    小 L 计划施展 $m$ 次魔法。每次,他会选择一个区间 $[l, r]$,然后施展以下 $3$ 大类、$7$ 种魔法之一:

    1. 魔力激发:令区间里每个水晶球中**特定属性**的能量爆发,从而使另一个**特定属性**的能量增强。具体来说,有以下三种可能的表现形式:

       - 火元素激发水元素能量:令 $A_i = A_i + B_i$。
       - 土元素激发火元素能量:令 $B_i = B_i + C_i$。
       - 水元素激发土元素能量:令 $C_i = C_i + A_i$。

       **需要注意的是,增强一种属性的能量并不会改变另一种属性的能量,例如 $A_i = A_i + B_i$ 并不会使 $B_i$ 增加或减少。**

    2. 魔力增强:小 L 挥舞法杖,消耗自身 $v$ 点法力值,来改变区间里每个水晶球的**特定属性**的能量。具体来说,有以下三种可能的表现形式:

       - 火元素能量定值增强:令 $A_i = A_i + v$。
       - 水元素能量翻倍增强:令 $B_i=B_i \cdot v$。
       - 土元素能量吸收融合:令 $C_i = v$。

    3. 魔力释放:小L将区间里所有水晶球的能量聚集在一起,融合成一个新的水晶球,然后送给场外观众。生成的水晶球每种属性的能量值等于区间内所有水晶球对应能量值的代数和。**需要注意的是,魔力释放的过程不会真正改变区间内水晶球的能量**。

    值得一提的是,小 L 制造和融合的水晶球的原材料都是定制版的 OI 工厂水晶,所以这些水晶球有一个能量阈值 $998244353$。当水晶球中某种属性的能量值大于等于这个阈值时,能量值会自动对阈值取模,从而避免水晶球爆炸。

    小 W 为小 L(唯一的)观众,围观了整个表演,并且收到了小 L 在表演中融合的每个水晶球。小 W 想知道,这些水晶球蕴涵的三种属性的能量值分别是多少。

由于矩阵的结合律和分配律成立,单点修改可以自然地推广到区间,即推出矩阵后直接用线段树维护区间矩阵乘积即可。

下面将举几个例子。

 $A_i = A_i + v$ 的转移

$$
\begin{bmatrix}
A & B & C & 1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
v & 0 & 0 & 1\\
\end{bmatrix}=
\begin{bmatrix}
A+v & B & C & 1\\
\end{bmatrix}
$$

 $B_i=B_i \cdot v$ 的转移

$$
\begin{bmatrix}
A & B & C & 1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & v & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1\\
\end{bmatrix}=
\begin{bmatrix}
A & B \cdot v & C & 1\\
\end{bmatrix}
$$

* * *

???+note "「LibreOJ 6208」树上询问"
    有一棵 $n$ 节点的树,根为 $1$ 号节点。每个节点有两个权值 $k_i, t_i$ ,初始值均为 $0$ 。

    给出三种操作:
    1. $\operatorname{Add}( x , d )$ 操作:将 $x$ 到根的路径上所有点的 $k_i\leftarrow k_i + d$
    2. $\operatorname{Mul}( x , d )$ 操作:将 $x$ 到根的路径上所有点的 $t_i\leftarrow t_i + d \times k_i$
    3. $\operatorname{Query}( x )$ 操作:询问点 $x$ 的权值 $t_x$ 

    $n,~m \leq 100000, ~-10 \leq d \leq 10$

若直接思考,下放操作和维护信息并不是很好想。但是矩阵可以轻松地表达。

$$
\begin{aligned}
\begin{bmatrix}k & t & 1 \end{bmatrix}
\begin{bmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
d & 0 & 1
\end{bmatrix}
&=
\begin{bmatrix}k+d & t & 1 \end{bmatrix}\\
\begin{bmatrix}k & t & 1 \end{bmatrix}
\begin{bmatrix}
1 & d & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{bmatrix}
&=
\begin{bmatrix}k & t+d \times k & 1 \end{bmatrix}
\end{aligned}
$$

### 定长路径统计

???+note "问题描述"