在遇到一些递推式时,如果我们直接按公式一步步进行运算,效率较低。构造矩阵进行快速运算,可以高效地解决这个问题。
以int型方阵为例:
矩阵结构:
struct Mat{ int mat[n][n]; };
矩阵乘法:
Mat mul(Mat a,Mat b) { Mat ret; memset(ret,0,sizeof(ret)); for(int i = 0; i<n; ++i) for(int j = 0; j<n; ++j) for(int k = 0; k<n; ++k) ret.mat[i][j] += a[i][k]*b[k][j]; return ret; }
快速计算方阵a的k次幂:
Mat matquickpow(Mat a,int k) { Mat ret; for(int i = 0; i<n; ++i) for(int j = 0; j<n; ++j) ret.mat[i][j] = (i == j); //初始化为单位矩阵 while(k){ if(k&1) ret = mul(a,a); a = mul(a,a); k >>= 1; } return ret; }
快速计算方阵a的k次幂对mod取模的一步运算:
Mat mulmod(Mat a,Mat b,int mod) { Mat ret; memset(ret,0,sizeof(ret)); for(int i = 0; i<n; ++i) for(int j = 0; j<n; ++j) for(int k = 0; k<n; ++k) ret.mat[i][j] = (ret.mat[i][j]+a[i][k]*b[k][j])%mod; //对于某些题目,当结果为负数不合题意时,可以对最终结果进行处理 //或者将此处改为ret.mat[i][j] = ((ret.mat[i][j]+a[i][k]*b[k][j])%mod+mod)%mod; return ret; }
快速计算方阵a的k次幂对mod取模:
Mat matquickpowmod(Mat a,int k,int m) { Mat ret; for(int i = 0; i<n; ++i) for(int j = 0; j<n; ++j) ret.mat[i][j] = (i == j); //初始化为单位矩阵 while(k){ if(k&1) ret = mulmod(a,a); a = mulmod(a,a); k >>= 1; } return ret; }
例如,对于斐波那契数列的递推部分,我们可以运用矩阵快速幂进行计算:
将Fn+2 = Fn+Fn+1转换为
就可以运用矩阵快速幂进行计算了。
时间: 2024-09-30 06:39:29