传送门
题意:给出矩阵A(n*m),B(m*n),求M=(A×B)^(n*n);再M%6
分析:很好,矩阵快速幂模板,先算C=A×B,M=C^(n*n)%6,直接爆栈,因为C最大为C(1000*1000)
可以把 M=(A×B)^(n*n)分解:M=(A×B)^(n*n)=A×[(B×A)^(n*n-1)]×B,因为C=B×A 矩阵最大为6×6
所以先对C^(n*n-1)得矩阵 M 加速,再算 A×M×B
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include<cstring>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e1+5;
ll n,m,mod=6;
ll A[1005][maxn],B[maxn][1005],C[maxn][maxn],f[1005][maxn];
ll ss[1002][1002];
int main()
{
while (~scanf("%lld%lld",&n,&m)&&n&&m){
memset(C,0,sizeof(C));
memset(f,0,sizeof(f));
memset(ss,0,sizeof(ss));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%lld",&A[i][j]);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%lld",&B[i][j]);
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=n;k++)
C[i][j]+=B[i][k]*A[k][j];
ll b=n*n-1,Matx[maxn][maxn]={0};
for(int i=1;i<=m;i++) Matx[i][i]=1;
while (b)
{
if(b&1){
ll s[maxn][maxn]={0};
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=m;k++)
s[i][j]+=C[i][k]*Matx[k][j]%mod;
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++) Matx[i][j]=s[i][j];
}
ll s[maxn][maxn]={0};
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=m;k++)
s[i][j]+=C[i][k]*C[k][j]%mod;
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++) C[i][j]=s[i][j];
b>>=1;
}
ll ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=m;k++)
f[i][j]+=A[i][k]*Matx[k][j],f[i][j]%=mod;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++)
ss[i][j]+=f[i][k]*B[k][j],ss[i][j]%=mod;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans+=ss[i][j];
printf("%lld\n",ans);
}
return 0;
}