矩阵快速幂(学习笔记)

矩阵乘法:设A是(n*m)的矩阵,B是(m*p)的矩阵,则(C=A*B)(n*p)的矩阵,(C_{i,j}=sum_{k=1}^{m} A_{i,k}*B_{k,j})(即矩阵C第i行第j列的数,是由A的第i行的m个数与B的第j列的m个数分别相乘再相加得到的)

for(int i=1;i<=n;i++)
	for(int j=1;j<=p;j++)
		for(int k=1;k<=m;k++)
			c[i][j]=c[i][j]+a[i][k]*b[k][j];

矩阵中有一类特殊的矩阵,它非常有用,称为单位矩阵.单位矩阵只有对角线上的数字是1,其余都是0,在矩阵乘法中它就相当于1,任何矩阵乘上单位矩阵还是等于本身.

矩阵快速幂用于求(A^k),其中A是一个矩阵,k是幂.模板还是快速幂的模板,只是快速幂中的"乘号"不再是数字与数字相乘的意思,而是矩阵与矩阵相乘的意思.

传送门:模板[矩阵快速幂]

LL mod=1e9+7,n,k;
struct mat{
    LL jz[105][105];
}a,b;
//用结构体来存储矩阵
//a是读入的矩阵,b是单位矩阵
mat mul(mat x,mat y){
    mat c;
    for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	    c.jz[i][j]=0;//记得赋初值为0
    for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
	    	for(int k=1;k<=n;k++)
				c.jz[i][j]=c.jz[i][j]%mod+(x.jz[i][k]*y.jz[k][j])%mod;
    return c;
}
mat quickpow(mat x,LL y){
    mat cnt=b;
//本来的快速幂中cnt=1,矩阵快速幂中cnt=单位矩阵b(相当于1)
    while(y){
		if(y&1)cnt=mul(cnt,x);
		x=mul(x,x);
//不再是数字乘数字,而是矩阵乘矩阵
		y/=2;
    }
    return cnt;
}
int main(){
    n=read();k=read();
    for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	    a.jz[i][j]=read();
    for(int i=1;i<=n;i++)b.jz[i][i]=1;
//构建出单位矩阵
    mat ans=quickpow(a,k);//直接快速幂
    for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
	    	printf("%lld ",ans.jz[i][j]%mod);
		printf("
");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/PPXppx/p/10386701.html