LeetCode 建信 04.电学实验课(矩阵快速幂,计数)
LeetCode 建信 04.电学实验课(矩阵快速幂,计数)
题目描述:
某电学实验使用了 row * col 个插孔的面包板,可视作二维矩阵,左上角记作 (0,0)。老师设置了若干「目标插孔」,它们位置对应的矩阵下标记于二维数组 position。实验目标要求同学们用导线连接所有「目标插孔」,即从任意一个「目标插孔」沿导线可以到达其他任意「目标插孔」。受实验导线长度所限,导线的连接规则如下:
一条导线可连接 相邻两列 的且 行间距 不超过 1 的两个插孔
每一列插孔中最多使用其中一个插孔(包括「目标插孔」)
若实验目标可达成,请返回使用导线数量最少的连接所有目标插孔的方案数;否则请返回 0。
注意:
输入数据保证每列最多仅有一个「目标插孔」;
答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1。
样例
输入:row = 5, col = 6, position = [[1,3],[3,2],[4,1]]
输出:0
解释:根据连接规则无法达成实验目标。
输入:row = 3,col = 4, position = [[0,3],[2,0]]
输出:3
解释:根据连接规则共有三种方案达成目标。
输入:row = 5, col = 6, position = [[1,3],[3,5],[2,0]]
输出:6
解释:根据连接规则共有六种方案达成目标。
限制
$1 <= row <= 20\
3 <= col <= 10^9\
1 < position.length <= 1000\
0 <= position[i][0] < row\
0 <= position[i][1] < col$
思路
由于每列只有一个插孔,所以连接顺序一定是从左到右一次连接,不会出现折返(这违反了”每一列插孔中最多使用其中一个插孔(包括「目标插孔」)”这个条件)。且每次前进一列一定只有三种连接方式:右上,右,右下。
将目标插孔按照列的大小排序,然后计算$position[i][1]$ 到$posistion[i-1][1]$两个相邻目标插孔间的方案数即可,最终答案就是 将这些相邻目标插孔方案数连乘起来。
考虑如何计算相邻目标插孔的方案数?我们先考虑相邻两列之间有哪儿些行可以转移,不妨设一个转移矩阵$T$,$T[i][j]$就代表当前一列的第$i$行可以转移到当前列的第$j$行。这个计算很简单:
1 |
|
但是目标插孔相邻两列之间的距离不一定是1,加入是2,那么令$T=T^2$,此时$T[i][j]$就代表了前两列的第$i$行到当前第$j$行的方案数。可以列的范围高达1e9,如果目标插孔相邻两列之间的距离为1e9那怎么办呢?直接$T^{1e9}$这是不合理的复杂度高达$O(n^3m)$, 考虑矩阵快速幂,对1e9进行二进制拆分即可。我们只需要预处理出$T,T^2,T^4,T^8….T^{2^{30}}$即可,每次只需要前一个平方即可递推出下一个,预处理复杂度是$O(30*n^3)$。
接下来逐一处理相邻两个目标插孔即可,d二进制拆分$logd$,每次$n^3$的复杂度的矩阵乘法。最后复杂度是$O(nlogmn^3)$。
代码
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!