Tr A
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
位运算(&)
&运算通常用于二进制的取位操作,如&1就是去二进制的最后一位
x&1==0为偶数,x&1= =1为奇数(都为1则为1,否则为0)
" >>": 去掉二进制的最后一位(除以2,相当于x/=2)
取模运算法则
取模运算规则(不适合除法)
a ^ b % p = ((a % p)^b) % p
(a * b) % p = (a % p * b % p) % p
(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p+p) % p ( a>=b)
本题题意比较好理解算一个矩阵快速幂的模板公式a ^ b % p = ((a % p)^b) % p
代码
#include<iostream>
#include<cstdio>
using namespace std;
const int mod=9973;
int n,k;
struct mat
{
int array[15][15];
}; //定义一个结构体表示矩阵
mat ori,unit;
mat mul(mat a,mat b)//矩阵相乘
{
mat c;
for(int i=0; i<n; i++){ //枚举第一个矩阵的行。
for(int j=0; j<n; j++) //枚举第二个矩阵的列。
{
c.array[i][j]=0;
for(int k=0; k<n; k++) //枚举元素。
c.array[i][j]=(c.array[i][j]+a.array[i][k]*b.array[k][j]%mod)%mod;
c.array[i][j]%=mod;
}
return c;
}
}
mat pow(mat a,mat b,int x)
{
while(x)
{
if(x&1) //x&1==0为偶数,x&1= =1为奇数
{
b=mul(b,a); //矩阵相乘
}
x>>=1; //" >>": 去掉二进制的最后一位(除以2,相当于x/=2)
a=mul(a,a); //矩阵相乘
}
return b;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)//多组输入到0结束
{
scanf("%d%d",&n,&k);
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
//对矩阵赋值
scanf("%d",&ori.array[i][j]);
unit.array[i][j]=ori.array[i][j];
}
}
mat res=pow(ori,ori,k-1);
int ans=0;
for(int i=0;i<n;i++)
ans=(ans+res.array[i][i])%mod; //记录((a % p)^b)
printf("%d\n",ans%mod); //记录a ^ b % p = ((a % p)^b) % p
}
return 0;
}