BSGS,只不过变成了矩阵。
学习了一下矩阵求逆,用高斯消元来做即可。
还是把系数矩阵放左面,右边的常数向量变成了一个单位矩阵。高斯消元即可,最后左边变成了一个单位矩阵,右边就是我们的逆矩阵。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 72
#define M 19999
#define k1 11113
#define k2 11117
#define ull unsigned long long
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,mod,h[M],num=0;
ull bin1[N],bin2[N];
inline int ksm(int x,int k){
int res=1;for(;k;k>>=1,x=x*x%mod) if(k&1) res=res*x%mod;return res;
}
inline int mo(int &x){x%=mod;x<0?x+=mod:x;}
struct Matrix{
int a[N][N];
int* operator[](int x){return a[x];}
void init(bool t){memset(a,0,sizeof(a));if(t) for(int i=1;i<=n;++i) a[i][i]=1;}
friend Matrix operator*(Matrix a,Matrix b){
Matrix res;res.init(0);
for(int i=1;i<=n;++i)
for(int k=1;k<=n;++k)
for(int j=1;j<=n;++j)
(res[i][j]+=a[i][k]*b[k][j])%=mod;return res;
}
}a,b;
inline Matrix inverse(Matrix a){
Matrix c;c.init(1);
for(int i=1;i<=n;++i){
int r=i;
while(r<=n&&!a[r][i]) ++r;
if(r!=i) for(int j=1;j<=n;++j) swap(a[i][j],a[r][j]),swap(c[i][j],c[r][j]);
int inv=ksm(a[i][i],mod-2);
for(int j=1;j<=n;++j) (a[i][j]*=inv)%=mod,(c[i][j]*=inv)%=mod;
for(int k=1;k<=n;++k){
if(k==i) continue;int t=a[k][i];
for(int j=1;j<=n;++j) mo(a[k][j]-=a[i][j]*t),mo(c[k][j]-=c[i][j]*t);
}
}return c;
}
struct Hashtable{
ull key;int val,next;
}data[M];
inline ull calhs(Matrix a){
ull res=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) res+=bin1[i-1]*bin2[j-1]*a[i][j];
return res;
}
inline void ins(ull key,int val){
int x=key%M;
for(int i=h[x];i;i=data[i].next){
if(data[i].key==key) return;
}data[++num].key=key;data[num].next=h[x];h[x]=num;data[num].val=val;
}
inline int hs(ull key){
int x=key%M;
for(int i=h[x];i;i=data[i].next){
if(data[i].key==key) return data[i].val;
}return -1;
}
int main(){
// freopen("a.in","r",stdin);
n=read();mod=read();bin1[0]=bin2[0]=1;
for(int i=1;i<=n;++i) bin1[i]=bin1[i-1]*k1,bin2[i]=bin2[i-1]*k2;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) a[i][j]=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) b[i][j]=read();
int m=sqrt(mod);Matrix x=b,y=inverse(a);
for(int i=0;i<m;++i){
ins(calhs(x),i);x=x*y;
}x.init(1);y.init(1);
for(int i=1;i<=m;++i) y=y*a;
for(int i=0;i<=m;++i){
int res=hs(calhs(x));x=x*y;
if(res==-1) continue;printf("%d\n",i*m+res);return 0;
}
}