矩阵快速幂可以想象为线性代数的矩阵相乘,主要是运用于高效的计算矩阵高次方。
将矩阵两两分组,若要求a^n,即知道a^(n/2)次方即可,矩阵快速幂便是运用的这个思路。
比方想求(A)^7那么(A)^6=(A*A)*(A*A)*(A*A),我们知道A*A此时再算三次便可得到答案,比起原先的计算已经简便了很多。
矩阵快速幂的主要思路是找到关键的那个矩阵,并把它构建出来,此时思路就基本差不多了。
举例:Hdu2604
题意:f和m两种字母组成字符串,fmf 和 fff 这种为不安全的字符串,现在有2*L个字母,问你有多少安全的字符串。答案mod M。
我们将0, 1, 2, 3, 4, 5的答案算出来我们便可以得到一个公式f(n)=f(n-1)+f(n-3)+f(n-4),此时我们要做的便是构建那个矩阵,如何构建呢。
我们可以得到这样的一个矩阵。
int n, modd; int a[4], f[4]; struct Matrix{ ll mat[4][4]; Matrix operator*(const Matrix& m)const{ Matrix tmp; for (int i=0; i <4; i++) { for (int j=0; j<4; j++) { tmp.mat[i][j]=0; for (int k=0; k<4; k++) { tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%modd; tmp.mat[i][j]%=modd; } } } return tmp; } }; ll Pow(Matrix &m, int k) { Matrix ans; memset(ans.mat, 0, sizeof(ans.mat)); for (int i = 0; i < 4; i++) ans.mat[i][i]=1; while(k) { if (k&1) ans=ans*m; k>>=1; m=m*m; } ll sum=0; for (int i = 0; i < 4; i++) { sum += ans.mat[0][i]*f[3-i]%modd; sum%=modd; } return sum%modd; } void solve() { Matrix m; f[0]=1, f[1]=2, f[2]=4, f[3]=6; while(scanf("%d%d", &n, &modd)!=EOF) { if (n<4) printf("%d ", f[n]%modd); else { memset(m.mat, 0, sizeof(m.mat)); m.mat[0][0]=m.mat[0][2]=m.mat[0][3]=1; m.mat[1][0]=m.mat[2][1]=m.mat[3][2]=1; printf("%d ", Pow(m, n-3)%modd); } } }