九度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\n",ans); 77 } 78 return 0; 79 }