版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41181771/article/details/83510076
题目链接: Tr A-杭电1575
Problem Description
A 为一个方阵,则 Tr A 表示 A 的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。
Input
数据的第一行是一个 T,表示有 T 组数据。
每组数据的第一行有 n(2 <= n <= 10) 和 k(2 <= k < 10^9) 两个数据。接下来有 n 行,每行有 n 个数据,每个数据的范围是 [0,9],表示方阵 A 的内容。
Output
对应每组数据,输出 Tr(A^k)%9973 。
Sample Input
2
2 2
1 0
0 1
3 99999999
1 2 3
4 5 6
7 8 9
Sample Output
2
2686
题意描述:
给你一个 n(1<n<11)阶方阵,让你计算出它的 k 次方(不用输出),并且最后输出它主对角线的所有元素之和。中间还有一个取模运算,意思是每次计算的值都要对 9973 进行取模,使它处于 0~9972 。
思想解析:
题目样例中给了 99999999 次方,所以肯定不能直接去算,直接算肯定超时的,所以这就涉及到了快速幂的思想,可以这么解释:每个十进制数都可以变换成二进制,比如21,换成二进制是10101,也就是 21 = 1+4+16 ,而计算机存储数字的方法就是变换成二进制,所以这个数的二进制位为 1 的时候,就乘,不是 1,就自乘。所以可以用右移的方法,来控制乘不乘。
有关快速幂思想的,可以参考整数快速幂这个博客,这里面讲的比较详细。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct Ride ///用结构体来存放矩阵比较方便
{
int e[20][20];
};
int n;
Ride ride(Ride a,Ride b) ///两个矩阵相乘
{
Ride c;
memset(c.e,0,sizeof(c.e));
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
for(int k=1; k<=n; k++)
c.e[i][j] = (c.e[i][j] + a.e[i][k] * b.e[k][j]) % 9973;
return c;
}
int main()
{
Ride rec,ans;
int t,k,sum;
cin >> t;
while(t--)
{
sum=0;
scanf("%d %d",&n,&k);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&rec.e[i][j]);
memset(ans.e,0,sizeof(ans.e));///将ans矩阵变成单位矩阵
for(int i=1; i<=n; i++)
ans.e[i][i]=1;
while(k)
{
if(k & 1) ///当k的最后一位是1时,ans*rec
ans=ride(ans,rec);
rec=ride(rec,rec);///每次循环 rec都要自乘
k >>= 1; ///k右移,相当于k/2
}
// for(int i=1; i<=n; i++) ///输出矩阵
// {
// for(int j=1; j<=n; j++)
// printf("%d ",ans.e[i][j]);
// cout << endl;
// }
for(int i=1; i<=n; i++) ///计算对角线和
sum = (sum+ans.e[i][i]) % 9973;
cout << sum % 9973 << endl;
}
return 0;
}