Tr A
Time Limit: 1000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
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 * n 矩阵的 k 次幂的迹,再模9973的值。
方法:矩阵快速幂
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxn 110
struct matrix{
int a[maxn][maxn];
}m1,m2;
int n,k;//n*n矩阵的k次方
//矩阵乘法
matrix matrixmul(matrix m1,matrix m2)
{
matrix result;
memset(result.a,0,sizeof(result.a));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
result.a[i][j]+=m1.a[i][k]*m2.a[k][j];
result.a[i][j]%=9973;//每次加完要对9973取模
}
}
}
return result;
}
//矩阵快速幂
matrix matrixpow(matrix m1,int k)
{
matrix result;
memset(result.a,0,sizeof(result.a));//初始化
for(int i=1;i<=n;i++)
{
result.a[i][i]=1;//将result化为单位矩阵
}
while(k!=0)//幂不为0时
{
//k为奇数时,第一次乘法的结果为矩阵本身
//所以要将m1乘以目前为单位矩阵的result
//然后k--
if(k%2!=0)
{
result=matrixmul(m1,result);
k-=1;
}
//k为偶数时,将m1乘以m1,相当于乘了两次
//将幂k除以2
else
{
m1=matrixmul(m1,m1);
k/=2;
}
}
return result;
}
/*
一种代码较少的模板,结果同样AC
matrix matrixpow(matrix m1,int k)
{
if(k==1) return m1;
matrix result=matrixpow(m1,k/2);
result=matrixmul(result,result);
if(k%2!=0) result=matrixmul(result,m1);
return result;
}
*/
int main()
{
int sum;//矩阵的迹
int t;
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>m1.a[i][j];
m1.a[i][j]%=9973;//注意避免溢出
}
}
m2=matrixpow(m1,k);
sum=0;
for(int i=1;i<=n;i++)
{
sum+=m2.a[i][i];//主对角线上各项和
sum%=9973;
}
cout<<sum<<endl;
}
return 0;
}