Leetcode 3700. Number of ZigZag Arrays II
- Leetcode 3700. Number of ZigZag Arrays II
- 1. 解题思路
- 2. 代码实现
- 题目链接:3700. Number of ZigZag Arrays II
1. 解题思路
这一题事实上就是上一题3699. Number of ZigZag Arrays I的进阶版本,主要的变化就是增加了nnn的复杂度,nnn最大可以取到10910^9109,因此暴力的迭代显然就不现实了,但其核心的迭代公式依然还是上一题中分析的那样:
{un+1i=∑j=i+1rdnjdn+1i=∑j=li−1unj\left\{ \begin{aligned} u_{n+1}^i &= \sum\limits_{j=i+1}^{r} d_{n}^{j} \\ d_{n+1}^i &= \sum\limits_{j=l}^{i-1} u_{n}^{j} \end{aligned} \right. ⎩⎨⎧un+1idn+1i=j=i+1∑rdnj=j=l∑i−1unj
这里,注意到,如果我们令v⃗=concat(u⃗,d⃗)\vec{v} = \mathop{concat}(\vec{u}, \vec{d})v=concat(u,d),那么事实上上述迭代过程可以写作是一个矩阵乘法:
v⃗n+1=M⋅v⃗n\vec{v}_{n+1} = M \cdot \vec{v}_{n} vn+1=M⋅vn
因此,不难推导:
v⃗n=Mn−1⋅v⃗1\vec{v}_{n} = M^{n-1} \cdot \vec{v}_{1} vn=Mn−1⋅v1
此时,问题也就变成了如何快速地求矩阵MMM的n−1n-1n−1了,这个就变成了一个常规的二分处理的算法了。
当然,既然这里涉及到了矩阵乘法,因此,我们自然而然就可以使用numpy来加速一下运算了,这里就不过多展开了。
2. 代码实现
给出python代码实现如下:
import numpy as npMOD = 10**9 + 7class Solution:def zigZagArrays(self, n: int, l: int, r: int) -> int:d = r-l+1vec = [1 for _ in range(d-1)] + [0] + [0] + [1 for _ in range(d-1)] vec = np.array(vec, dtype=object)M = [[0 for _ in range(2*d)] for _ in range(2*d)]for i in range(d):for j in range(i+1, d):M[i][d+j] = 1for j in range(i):M[i+d][j] = 1M = np.array(M, dtype=object)def pow_mul(M, vec, n):res = vecwhile n:if n % 2 == 1:res = (M @ res) % MODM = (M @ M) % MODn = n // 2return res res = pow_mul(M, vec, n-1)return sum(res) % MOD
提交代码评测得到:耗时4045ms,占用内存31.78MB。