hdu 1575 Tr A (矩阵快速幂入门题)

题目

先上一个链接:十个利用矩阵乘法解决的经典题目

这个题目和第二个类似

由于矩阵乘法具有结合律,因此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 }

 

posted @ 2014-04-01 21:00  水门  阅读(312)  评论(0编辑  收藏  举报