先上一个链接:十个利用矩阵乘法解决的经典题目
这个题目和第二个类似
由于矩阵乘法具有结合律,因此A^4 = A * A * A * A = (A*A) * (A*A) = A^2 * A^2。我们可以得到这样的结论:当n为偶数时,A^n = A^(n/2) * A^(n/2);当n为奇数时,A^n = A^(n/2) * A^(n/2) * A (其中n/2取整)。这就告诉我们,计算A^n也可以使用二分快速求幂的方法。例如,为了算出A^25的值,我们只需要递归地计算出A^12、A^6、A^3的值即可。根据一些结果,我们可以在计算过程中不断取模,避免高精度运算。
思路:如果直接相乘的话,时间复杂度是O(n*n*k)。
耗时太长,这里可以采用二分的思想。
另设置一个b[]数组,存储k为奇数的时候的 a[]矩阵的乘积。
k为偶数时,直接把a[]相乘,就相当于使k次相乘减少了一半。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int mo = 9973; 7 int n, ans; 8 9 struct node 10 { 11 int m[11][11]; 12 }; 13 node mult(node a, node b) 14 { 15 node c; 16 int i, j, k; 17 for(i = 1; i <= n; i++) 18 for(j = 1; j <= n; j++) 19 { 20 c.m[i][j] = 0; 21 for(k = 1; k <= n; k++) 22 c.m[i][j] += a.m[i][k]*b.m[k][j]; 23 c.m[i][j] %= mo; 24 } 25 return c; 26 } 27 int main() 28 { 29 node a, b; 30 int t, k; 31 int i, j; 32 cin>>t; 33 while(t--) 34 { 35 ans = 0; 36 cin>>n>>k; 37 for(i = 1; i <= n; i++) 38 for(j = 1; j <= n; j++) 39 { 40 cin>>a.m[i][j]; 41 if(i == j) 42 b.m[i][j] = 1; 43 else 44 b.m[i][j] = 0; 45 } 46 while(k > 1) 47 { 48 if(k%2==1) 49 { 50 k--; 51 b = mult(a, b); 52 } 53 else 54 { 55 k = k/2; 56 a = mult(a, a); 57 } 58 } 59 b = mult(a, b); 60 for(i = 1; i <= n; i++) 61 { 62 ans += b.m[i][i]; 63 ans %= mo; 64 } 65 cout<<ans<<endl; 66 } 67 return 0; 68 }