• 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
    ", Baby_Step_Giant_Step(A, B));
    }
    
    
  • 相关阅读:
    数1的个数
    找水王2
    书店促销
    返回一个二维整数数组中最大联通子数组的和
    敏捷软件开发读书笔记(三)
    软件工程团队开发——第一次冲刺会议总结
    返回一个二维整数数组中最大联通子数组的和
    结对项目开发电梯调度
    《最后期限》——读书笔记03
    最后期限——阅读笔记2
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039309.html
Copyright © 2020-2023  润新知