• 九度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 }
  • 相关阅读:
    nginx设置开机自启
    sublimeText3和phpstrom使用
    快捷键整理
    nginx日志分割及备份
    nginx日志设置
    nginx上部署PHP
    C语言三种参数传递方式
    浮点数在内存中的存储方式
    windows下git安装过程
    偏移二进制编码和二进制补码的区别
  • 原文地址:https://www.cnblogs.com/jasonJie/p/5837137.html
Copyright © 2020-2023  润新知