您的位置:首页 > 其它

hdu1575 Tr A(矩阵快速幂)

2016-11-15 19:50 429 查看


Tr A

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4553    Accepted Submission(s): 3432


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

给定矩阵A,请快速计算出A^n(n个A相乘)的结果,输出的每个数都mod p。
 
  由于矩阵乘法具有结合律,因此A^4 = A * A * A * A = (A*A) * (A*A) = A^2 * A^2。我们可以得到这样的结论:当n为偶数时,A^n = A^(n/2) * A^(n/2);当n为奇数时,A^n
= A^(n/2) * A^(n/2) * A (其中n/2取整)。
这就告诉我们,计算A^n也可以使用二分快速求幂的方法。例如,为了算出A^25的值,我们只需要递归地计算出A^12、A^6、A^3的值即可。根据这里的一些结果,我们可以在计算过程中不断取模,避免高精度运算。 

#include<cstdio>
#include<cstring>
typedef struct Node
{
int map[11][11];
}Martic;
Martic A,B;
int n,kk;
Martic cal(Martic a,Martic b)
{
Martic r;
memset(r.map,0,sizeof(r.map));
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
if(a.map[i][k]<=0)  //剪枝
continue;
for(int j=0;j<n;j++)
{
if(b.map[k][j]<=0)  //剪枝
continue;
r.map[i][j]+=a.map[i][k]*b.map[k][j];
r.map[i][j]%=9973;
}
}
}
return r;
}
Martic quick()
{
Martic q,p;
q=A;
p=B;
while(kk)
{
if(kk%2==1)
p=cal(q,p);
q=cal(q,q);
kk=kk/2;
}
return p;
}
int main()
{
int t;
Martic C;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&kk);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
scanf("%d",&A.map[i][j]);
B.map[i][j]=(i==j);
}
C=quick();
int sum=0;
for(int i=0;i<n;i++)
{
sum+=C.map[i][i];
sum%=9973;
}
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: