题目链接:点击打开链接
两个矩阵A,B,求(A*B)的N*N次幂。其中元素都%6
因为N范围是1000,K范围是6,如果直接对A*B快速幂的话是对一个1000*1000的矩阵操作,会TLE。所以可以先求出B*A的(N*N-1)次方,这是一个5*5的矩阵,再右乘A左乘B。
快速幂模板还是写vector的比较好
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
struct mat{
int n,m;
vector<vector<int> >a;
mat(int n,int m):n(n),m(m){
a.resize(n);
for(int i=0;i<n;i++){
a[i].resize(m,0);
}
}
friend mat operator *(const mat &T,const mat &V){
mat tmp(T.n,V.m);
for(int i=0;i<T.n;i++){
for(int j=0;j<T.m;j++){
for(int k=0;k<V.m;k++){
tmp.a[i][k]+=T.a[i][j]*V.a[j][k];
tmp.a[i][k]%=6;
}
}
}
return tmp;
}
mat pow(int p){
mat tmp(n,n);
mat k(n,n);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
k.a[i][j]=a[i][j];
}
}
for(int i=0;i<n;i++){
tmp.a[i][i]=1;
}
while(p){
if(p&1){
tmp=tmp*k;
}
k=k*k;
p>>=1;
}
return tmp;
}
};
int main(){
int N,K;
while(~scanf("%d%d",&N,&K)){
if(!N&&!K) break;
mat x(N,K);
for(int i=0;i<N;i++){
for(int j=0;j<K;j++){
scanf("%d",&x.a[i][j]);
}
}
mat y(K,N);
for(int i=0;i<K;i++){
for(int j=0;j<N;j++){
scanf("%d",&y.a[i][j]);
}
}
mat c(K,K);
c=y*x;
mat res(N,N);
res=c.pow(N*N-1);
res=x*res;
res=res*y;
int ans=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
ans+=res.a[i][j];
}
}
printf("%d\n",ans);
}
return 0;
}