标签:
矩阵快速幂可认为是快速幂算法的扩展。
有一种借助于 typedef 的较为方便的写法。
1 #define MAX_D 100 2 #define mod 1000000007 3 4 typedef long long ll; 5 typedef ll mat[MAX_D][MAX_D]; 6 typedef ll vec[MAX_D];
采用这种方式定义矩阵,既简洁又可以很方便地调用 memset, memcpy 等函数。
矩阵(方阵)乘法,推荐写成参数较少的形式
mat_mul(mat a, mat b, int dim)
其中 a 相当于目的操作数 (destination),b 相当于源操作数 (source),结果 (result) 存在 a 中。
1 void mat_mul(mat a, mat b, int dim){ 2 mat res; 3 memset(res, 0, sizeof(mat)); 4 for(int i=0; i<dim; i++) 5 for(int j=0; j<dim; j++) 6 if(a[i][j]) 7 for(int k=0; k<dim; k++) 8 res[i][k]+=a[i][j]*b[j][k], 9 res[i][k]%=mod; 10 memcpy(a, res, sizeof(mat)); 11 }
这种写法还针对稀疏矩阵进行了优化。
还可以重载 (overload) 一个行向量乘方阵的版本。
注意:数学上一般将向量视做列矩阵,但在某些涉及状态转移矩阵的计数问题中,将“向量” (其实这里是否称作向量也无关紧要)视作行矩阵更方便。
1 void mat_mul(vec a, mat b, int dim){ 2 vec res; 3 memset(res, 0, sizeof(vec)); 4 for(int i=0; i<dim; i++) 5 for(int j=0; j<dim; j++) 6 res[j]+=a[i]*b[i][j], 7 res[j]%=mod; 8 memcpy(a, res, sizeof(vec)); 9 }
快速幂采用的是非递归的写法
1 void mat_pow(mat a, int dim, int n){ 2 mat res; 3 memset(res, 0, sizeof(res)); 4 for(int i=0; i<dim; i++) 5 res[i][i]=1; 6 mat tmp; 7 memcpy(tmp, a, sizeof(mat)); 8 while(n){ 9 if(n&1){ 10 mat_mul(res, tmp, dim); 11 n--; 12 } 13 else{ 14 mat_mul(tmp, tmp, dim); 15 n>>=1; 16 } 17 } 18 memcpy(a, res, sizeof(mat)); 19 }
这里仍然采用的是参数较少的写法,如果需要保留矩阵 a (a 往往是状态转移矩阵),就把第2行移到参数里。
标签:
原文地址:http://www.cnblogs.com/Patt/p/4684334.html