组合数学中的线性代数方法
瞎写一通
参考资料:https://sites.google.com/view/jozsefbaloghmath/teaching/math584
1.矩阵乘法
问题1.1:判断一个图中是否有三角形
暴力做是\(O(n^3)\)的
考虑该图的邻接矩阵\(A\),枚举图的每条边\((a,b)\),我们想要判断是否存在\(c\)使得存在边\((a,c),(c,b)\),也就是\(A_{a,c}=A_{c,b}=1\)
\(A^2_{a,b}=\sum_{c=1}^nA_{a,c}A_{c,b}\),所以当\(A^2_{a,b}>0\),存在\(c\)使得\(A_{a,c}=A_{c,b}=1\)。所以我们可以使用\(O(n^{2.373})\)的矩阵乘法求解\(A^2\)后判断。
问题1.2:判断\(01\)矩阵\(A,B\)的乘积是否等于\(C\)
本部分会介绍Freivalds算法
暴力判断(用快速矩阵乘法)是\(O(n^{2.373})\)的,然而我们可以随机化:
均匀随机一个\(01\)向量\(x\),判断\(ABx\)是否等于\(Cx\)。
\(ABx=A(Bx)\),所以能在\(O(n^2)\)的事件内计算\(ABx,Cx\)并判断。显然这个做法不会在\(AB=C\)时出错。
当\(AB\neq C\),\((AB-C)\)至少有一行(设其为\(r\))非全\(0\)。那么\(r\cdot x=0\)时出错。
由于\(r\)的每一个位置地位相等,所以我们可以假设\(r\)的所有\(1\)处于前\(1,...,k\)列。
当\(r\cdot x=0\),\(x\)的前\(1,...,k\)个元素有偶数个为\(1\),错误概率为\(\dfrac{\sum_{0\leq 2i\leq k}\dbinom{k}{2i}}{2^k}\)
根据熟知等式\(\sum_{0\leq 2i\leq k}=2^{k-1}\),所以在这一行错误判断概率为\(\frac{1}{2}\)。
随机\(l\)次错误率为\(\frac{1}{2^l}\)
问题1.3:递推问题
在一交换环\((+,\cdot)\)上,定义递推数列\(f_i=\sum_{k=1}^nf_{i-k}\cdot a_i\),给定初值\(f_1,...,f_k\),我们想要快速求\(f_n\)。
构造\(x=[f_k,...,f_1]^T\),我们构造\(M\),使得\(M^lx=[f_{k+a},...,f_{1+a}]^T\)。考虑让\(M[f_{k+a},...,f_{1+a}]^T=[f_{k+a+1},...,f_{2+a}]^T\)
使\(M_{i+1,i}=1\),\(M_{1,i}=a_{k-i+1}\) (\(1\leq i<k\)), \(M\)的其他元素为\(0\)
这个做法的瓶颈在于矩阵乘法,考虑使用多项式取模优化。
令\(h(x)=x^k-\sum_{k=1}^ka_ix^{k-i},x^n=f(x)h(x)+r(x)\)(对\(x^n\)使用多项式长除法),那么\(\sum_{i=0}^{k-1}r(x)[x^i]a_{k-i}=f_n\)
证明:考虑一个序列\(b\)以及一个函数\(F(b)=\sum_{i\geq 0}b_if_i\)
当\(n\geq k\)时,根据\(f_n\)的定义,对于任意环的元素\(s\),将\(b_n\)减去\(s\),并且对于所有\(1\leq i\leq k\)将\(b_{n-i}\)加上\(sc_i\)后\(F(b)\)不会改变
所以如果我们想要找到\(f_n\)并且\(n\geq k\),我们可以先令\(b_n=1\),并且令\(b\)的所有其他元素为\(0\)。
然后将\(b_{n-i},1\leq i\leq k\)加上\(b_n\),将\(b_n\)变成\(0\),将\(n\)减去\(1\)。重复以上过程直到\(n<k\),\(\sum_{i=1}^{k-1}b_ia_{k-i}=f_n\)。
令\(f(x)=\sum_{n\geq 1}x^nf_i\),那么每一步等于对\(f(x)\)对\(h(x)\)做长除法,并且停止条件也是\(\deg(f(x))\leq \deg(h(x))\)
所以\(\sum_{i=0}^{k-1}r(x)[x^i]a_{k-i}=f_n\)。
问题1.4:一些图论问题
设图有\(n\)个点。
首先是如果我们要查询两个节点\(a,b\)之间经过\(k\)条边的路径的条数,我们可以考虑图的邻接矩阵\(A\),\(A^k_{a,b}\)就是答案(归纳易证)。
这样子时间复杂度是\(O(n^3\log_2k)\)。
如果有多次查询,我们可以预处理\(A^{2^i}\)。考虑一个向量\(x\),初始\(x_a=1\),\(x\)的其他元素为\(0\),那么\((A^{k}x)_b\)就是答案。
由于向量乘矩阵时间复杂度是\(O(n^2)\),我们可以拆位,设\(k\)拥有二进制位\(2^a_0,2^a_1,...2^{a_l}\),我们可以将\(x\)左乘\(A^{2^{a_0}},...,A^{2^{a_n}}\),一次询问就是\(O(n^2\log_2k)\)的
现在如果我们要查询两个节点\(a,b\)之间经过\(k\)条边的最短路径,我们可以考虑使用\((\min,+)\)矩阵乘法:\(C=AB,C_{i,j}=\min_k(A_{i,k}+B_{k,j})\)
那么那么\((A^{k}x)_b\)就是答案。同理可以使用上面的预处理优化时间复杂度(注意\((\min,+)\)矩阵乘法目前人类没有发现\(O(n^{3-\epsilon}),\epsilon>0\)的做法)
对于上述算法的一个运用是LOJ539:

浙公网安备 33010602011771号