题目链接: Tr A-杭电1575
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8088 Accepted Submission(s): 5883
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 Iutput
2
2 2
1 0
0 1
3 99999999
1 2 3
4 5 6
7 8 9
Sample Output
2
2686
题意描述:
给你一个 n(1
思想解析:
题目样例中给了 99999999 次方,所以肯定不能直接去算,直接算肯定超时的,所以这就涉及到了快速幂的思想,可以这么解释:每个十进制数都可以变换成二进制,比如21,换成二进制是10101,也就是 21 = 1+4+16 ,而计算机存储数字的方法就是变换成二进制,所以这个数的二进制位为 1 的时候,就乘,不是 1,就自乘。所以可以用右移的方法,来控制乘不乘。
有关快速幂思想的,可以参考整数快速幂这个博客,这里面讲的比较详细。
代码篇:
#include
#include
#include
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;
}