bzoj4128 Matrix(BSGS+高斯消元,矩阵求逆+Hash表)

BSGS,只不过变成了矩阵。
学习了一下矩阵求逆,用高斯消元来做即可。 O(n3)
还是把系数矩阵放左面,右边的常数向量变成了一个单位矩阵。高斯消元即可,最后左边变成了一个单位矩阵,右边就是我们的逆矩阵。

#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;
    }
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80139009