九度oj 题目1443:Tr A

题目描述:

A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。

输入:

数据的第一行是一个T,表示有T组数据。
每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据。接下来有n行,每行有n个数据,每个数据的范围是[0,9],表示方阵A的内容。

输出:

对应每组数据,输出Tr(A^k)%9973。

样例输入:
2
2 2
1 0
0 1
3 99999999
1 2 3
4 5 6
7 8 9
样例输出:
2
2686

这个题考查矩阵相乘和幂的快速运算
对于幂的快速运算
考虑 m 的 n 次幂
n 可以写为 几个二的平方项的和
比如n 为 10, 二进制位 1010, 8 + 2
那么m 的 10 次幂 等于 m的8次幂 乘以 m的二次幂
通过不断的乘方运算,即可得出答案

代码如下
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #define M 9973
 5 int t, n, k;
 6 int num[12][12];
 7 int res[12][12];
 8 
 9 void multi() {
10     int num2[12][12], num3[12][12];
11     for(int i = 0; i < n; i++) {
12         for(int j = 0; j < n; j++) {
13             num2[i][j] = num[i][j];
14             num3[i][j] = 0;
15         }
16     }
17     for(int i = 0; i < n; i++) {
18         for(int j = 0; j < n; j++) {
19             for(int k = 0; k < n; k++) {
20                 num3[i][j] = (num3[i][j] + num[i][k] * num2[k][j])%M;
21             }
22         }
23     }
24     for(int i = 0; i < n; i++) {
25         for(int j = 0; j < n; j++) {
26             num[i][j] = num3[i][j];
27         }
28     }
29 }
30 
31 void multiR() {
32     int num3[12][12];
33     memset(num3, 0, sizeof(num3));
34     for(int i = 0; i < n; i++) {
35         for(int j = 0; j < n; j++) {
36             for(int k = 0; k < n; k++) {
37                 num3[i][j] = (num3[i][j] + num[i][k] * res[k][j])%M;
38             }
39         }
40     }
41     for(int i = 0; i < n; i++) {
42         for(int j = 0; j < n; j++) {
43             res[i][j] = num3[i][j];
44         }
45     }
46 }
47 
48 int main(int argc, char const *argv[])
49 {
50     int t;
51     scanf("%d",&t);
52     while(t--) {
53         scanf("%d %d",&n,&k);
54         for(int i = 0; i < n; i++) {
55             for(int j = 0; j < n; j++) {
56                 scanf("%lld",&num[i][j]);
57             }
58         }
59         int p = k;
60         memset(res, 0, sizeof(res));
61         for(int i = 0; i < n; i++) {
62             res[i][i] = 1;
63         }
64         while(p > 0) {
65             if(p&1) {
66                 multiR();
67             }
68             multi();
69             p >>=1;
70         }
71         
72         int ans = 0;
73         for(int i = 0; i < n; i++) {
74             ans = (ans + res[i][i])%M;
75         }
76         printf("%d
",ans);
77     }
78     return 0;
79 }
原文地址:https://www.cnblogs.com/jasonJie/p/5837137.html