BZOJ 4128: Matrix (矩阵BSGS)

类比整数的做法就行了

1A爽哉

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 75;
const int sed = 137;
int n, p;
struct Matrix {
    int v[MAXN][MAXN];
    Matrix(){ memset(v, 0, sizeof v); }
    inline void read() {
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                scanf("%d", &v[i][j]);
    }
    inline int hash() {
        int re = 0;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                re = re * sed + v[i][j];
        return re;
    }
    inline Matrix operator *(const Matrix &o)const {
        Matrix re;
        for(int k = 1; k <= n; ++k)
            for(int i = 1; i <= n; ++i) if(v[i][k])
                for(int j = 1; j <= n; ++j) if(o.v[k][j])
                    re.v[i][j] = (re.v[i][j] + v[i][k] * o.v[k][j]) % p;
        return re;
    }
    inline bool operator ==(const Matrix &o)const {
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                if(v[i][j] != o.v[i][j]) return 0;
        return 1;
    }
}Zero, One;
inline Matrix qpow(Matrix a, int b) {
    Matrix re = One;
    while(b) {
        if(b & 1) re = re * a;
        a = a * a; b >>= 1;
    }
    return re;
}
map<int, int>myhash;
inline int Baby_Step_Giant_Step(Matrix a, Matrix b) {
    if(b == One) return 0;
    myhash.clear();
    int m = int(sqrt(p)+1);
    Matrix base = b;
    for(int i = 0; i < m; ++i) {
        myhash[base.hash()] = i;
        base = a * base; //这里写a*base 和 base*a 都是一样的,因为两边同时乘以矩阵,可以乘在左边也可以乘在右边
    }
    Matrix tmp = One;
    base = qpow(a, m);
    for(int i = 1, j; i <= m+1; ++i) {
        tmp = tmp * base;
        if(myhash.count(j=tmp.hash()))
            return i*m - myhash[j];
    }
    return -1;
}
inline void Pre_Work() {
    for(int i = 1; i <= n; One.v[i][i] = 1, ++i);
}
int main() {
    scanf("%d%d", &n, &p);
    Pre_Work();
    Matrix A, B;
    A.read(); B.read();
    printf("%d\n", Baby_Step_Giant_Step(A, B));
}

posted @ 2019-12-14 14:51  _Ark  阅读(128)  评论(0编辑  收藏  举报