http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=10959
题意,给一个n*n的矩阵A,求A+A^2+A^3+A^4+A^5+A^6+```+A^k, 矩阵对m取mod.
有种东西叫二分- -
----------------------------------------------------------------------------------------------------------------------------
if(k&1) 如果k为奇数,我们计算要加上A^k
如果k为偶数,我们直接计算 I+A^(k>>1),其中I是单位矩阵,然后递归计算A+A^2+```+A^(k>>1)
至于为什么呢,你可以把式子(I+A^(k>>1))(A+A^2+```+A^(k>>1))展开还原(偶数情况)
奇数情况需要加上最后一项。
然后递归计算+快速幂取模
我重载了矩阵的 *,+,^,然后写计算前k项和就比较好些。
(一开始样例都没过,重载的时候忘记返回了- -||)
初学矩阵的蒟蒻- -
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
const int maxn=35;
int n,m,k;
struct Mat
{
int mat[maxn][maxn];
Mat()
{
memset(mat,0,sizeof(mat));
}
}ans;
Mat operator+(Mat a,Mat b)
{
Mat c;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
c.mat[i][j]+=a.mat[i][j]+b.mat[i][j];
c.mat[i][j]%=m;
}
}
return c;
}
Mat operator*(Mat a,Mat b)
{
Mat c;
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]%m*b.mat[k][j]%m)%m;
}
}
}
return c;
}
Mat operator^(Mat a,int y)
{
Mat c;
for(int i=1;i<=n;i++)c.mat[i][i]=1;
for(;y;y>>=1)
{
if(y&1)c=c*a;
a=a*a;
}
return c;
}
Mat S(Mat a,int y)
{
if(y==1)return a;
Mat tmp;
for(int i=1;i<=n;i++)tmp.mat[i][i]=1;
tmp=tmp+(a^(y>>1));
tmp=tmp*S(a,y>>1);
if(y&1)
{
tmp=tmp+(a^y);
}
return tmp;
}
int main()
{
while(scanf("%d%d%d",&n,&k,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)scanf("%d",&ans.mat[i][j]);
}
ans=S(ans,k);//求和
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)printf("%d ",ans.mat[i][j]);
printf("\n");
}
}
return 0;
}