循环矩阵及其应用
循环矩阵及其应用
引入
在信息学竞赛中,矩阵是一个非常常用的知识点,而其中矩阵乘法的时间复杂度为 \(O(n^3)\)。但是其中一些矩阵拥有特殊的构造,使得它能够更快的求解,例如我们今天需要了解的循环矩阵,它的求解复杂度可以优化到 \(O(n^2)\) 甚至 \(O(n\log_2{n})\)(但是我不会)。
分析
设循环矩阵 \(A\),它的内部排列大概是这样的:
\[A =
\begin{bmatrix}
a_{1,1} & \cdots & a_{1,n-1} & a_{1,n} \\
\vdots & \ddots & \vdots & \vdots \\
a_{n-1,1} & \cdots & a_{n-1,n-1} & a_{n-1,n} \\
a_{n,1} & \cdots & a_{n,n-1} & a_{n,n} \\
\end{bmatrix}
=
\begin{bmatrix}
b_{1} & \cdots & b_{3} & b_{2} \\
\vdots & \ddots & \vdots & \vdots \\
b_{n-1} & \cdots & b_{1} & b_{n} \\
b_{n} & \cdots & b_{2} & b_{1} \\
\end{bmatrix}\\
\]
我们通过普通的矩阵乘法可以把它计算出来:
\[\begin{aligned}
A' = A \times A & =
\begin{bmatrix}
a_{1,1} & \cdots & a_{1,n-1} & a_{1,n} \\
\vdots & \ddots & \vdots & \vdots \\
a_{n-1,1} & \cdots & a_{n-1,n-1} & a_{n-1,n} \\
a_{n,1} & \cdots & a_{n,n-1} & a_{n,n} \\
\end{bmatrix}
\begin{bmatrix}
a_{1,1} & \cdots & a_{1,n-1} & a_{1,n} \\
\vdots & \ddots & \vdots & \vdots \\
a_{n-1,1} & \cdots & a_{n-1,n-1} & a_{n-1,n} \\
a_{n,1} & \cdots & a_{n,n-1} & a_{n,n} \\
\end{bmatrix}\\
& =
\begin{bmatrix}
b_{1} & \cdots & b_{3} & b_{2} \\
\vdots & \ddots & \vdots & \vdots \\
b_{n-1} & \cdots & b_{1} & b_{n} \\
b_{n} & \cdots & b_{2} & b_{1} \\
\end{bmatrix}
\begin{bmatrix}
b_{1} & \cdots & b_{3} & b_{2} \\
\vdots & \ddots & \vdots & \vdots \\
b_{n-1} & \cdots & b_{1} & b_{n} \\
b_{n} & \cdots & b_{2} & b_{1} \\
\end{bmatrix}\\
&=
\begin{bmatrix}
\sum_{(i+j-2)\pmod n + 1 = 1} b_i \times b_j & \cdots & \sum_{(i+j-2)\pmod n + 1 = 2} b_i \times b_j \\
\vdots & \ddots & \vdots \\
\sum_{(i+j-2)\pmod n + 1 = n} b_i \times b_j & \cdots & \sum_{(i+j-2)\pmod n + 1 = 1} b_i \times b_j \\
\end{bmatrix}\\
\end{aligned}
\]
那么接下来的事情就一目了然了,我们在计算时单取矩阵的第一列(行)进行计算,就可以优化到 \(O(n^2)\) 了。
所以就可以打出一份循环矩阵的模版:
template<class T,const int N>struct CMat{
int n;
T d[N];
T &operator[](int i){
return d[i];
}
CMat(int n=0):n(n){
FOR(i,1,n)d[i]=0;
}
void Unit(){
d[1]=1;
}
friend CMat operator *(CMat A,CMat B){
CMat C(A.n);
FOR(i,1,A.n)FOR(j,1,B.n)C[(i+j-2)%C.n+1]+=A[i]*B[j];
return C;
}
friend CMat operator ^(CMat A,ll b){
CMat res(A.n);
for(res.Unit();b;b>>=1,A=A*A)if(b&1)res=res*A;
return res;
}
};
应用
BZOJ - 2510/4204
链接
分析
在每一次操作中,每个小球被重新编号的概率是 \(\frac{1}{m}\),而不改变的概率是 \(\frac{m-1}{m}\),那么如果我们设 \(f_{i,j}\) 表示经过了 \(i\) 次操作后,标号为 \(j\) 的球的期望个数,就可以列出如下的转移方程:
\[\begin{bmatrix}
f_{i,1} & f_{i,2} & \cdots & f_{i,n} \\
\end{bmatrix}
\begin{bmatrix}
\frac{m-1}{m} & \frac{1}{m} & \cdots & 0 \\
0 & \frac{m-1}{m} & \cdots & 0 \\
\vdots & \vdots & \ddots & \vdots \\
\frac{1}{m} & 0 & \cdots & \frac{m-1}{m} \\
\end{bmatrix}
=
\begin{bmatrix}
f_{i+1,1} & f_{i+1,2} & \cdots & f_{i+1,n} \\
\end{bmatrix}
\]
其中的转移矩阵明显是一个循环矩阵,我们用循环矩阵的方式优化矩阵快速幂就可以达到 \(O(n^2\log_2{k})\) 的时间复杂度,可以过掉本题。

浙公网安备 33010602011771号