Loading

【题解】【BZOJ】BZOJ4128 Matrix

 

 

BZOJ4128 Matrix

BZOJ4128 Matrix

1 题外话

调了半天竟是因为比较函数打错

2 sol

矩阵离散对数

令\(x=A\lceil \sqrt{p} \rceil -B\) ,其中\(0\leqslant A,B \leq \lceil \sqrt{p} \rceil\)

则有\(a^{A\sqrt{p}-B} = b\)

所以\(a^{A\sqrt{p}}=ba^{B}\)

枚举$B$,得到右侧所有取值,存进map里,再枚举\(A\) ,寻找是否有对应的B

找到后\(x=A\lceil \sqrt{p} \rceil -B\)

时间复杂度\(O(\sqrt{p})\)

和正常BSGS的推导毫无区别

3 code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
using namespace std;

const int N=80;

inline void read(int &x) {
    x=0;
    int f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if (ch=='-') {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    x*=f;
}

int n,p;

struct mat {
    int a[N][N];
    mat() {
        memset(a,0,sizeof(a));
    }
    inline void init() {
        for(int i=1;i<=n;i++) {
            a[i][i]=1;
        }
    }
    inline void input() {
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                read(a[i][j]);
            }
        }
    }
    inline void output() {
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                printf("%d ",a[i][j]);
            }
            puts("");
        }
    }
};

mat I;

mat operator * (const mat &x,const mat &y) {
    mat ans;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            for(int k=1;k<=n;k++) {
                ans.a[i][j]+=x.a[i][k]*y.a[k][j];
                ans.a[i][j]%=p;
            }
        }
    }
    return ans;
}

bool operator == (const mat &x,const mat &y) {
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            if (x.a[i][j]!=y.a[i][j]) {
                return 0;
            }
        }
    }
    return 1;
}

bool operator < (const mat &x,const mat &y) {
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            if (x.a[i][j]<y.a[i][j]) {
                return 1;
            }
            if (x.a[i][j]>y.a[i][j]) {
                return 0;
            }
        }
    }
    return 0;
}

inline mat mat_pow(mat base,int p) {
    mat ans;
    ans.init();
    while(p) {
        if (p&1) {
            ans=ans*base;
        }
        base=base*base;
        p>>=1;
    }
    return ans;
}

inline int BSGS(mat a,mat b) {
    if (b==I) {
        return 0;
    }
    map<mat,int> mp;
    int m=ceil(sqrt(p));
    mat ax=b;
    mp[ax]=0;
    for(int i=1;i<=m;i++) {
        ax=ax*a;
        mp[ax]=i;
    }
    mat am=mat_pow(a,m);
    mat aj=am;
    for(int i=1;i<=m;i++) {
        if (mp[aj]) {
            return i*m-mp[aj];
        }
        aj=aj*am;
    }
    return -1;
}

int main() {
    read(n),read(p);
    I.init();
    mat A,B;
    A.input();
    B.input();
    printf("%d\n",BSGS(A,B));
    return 0;
}

4 注意

map要重载小于运算符和等于运算符

小于的重载最后如果写成return 1就会找不到目标,原因不明

Author: tt66ea

Created: 2021-07-16 周五 19:54

Validate

posted @ 2021-07-16 19:57  tt66ea蒟蒻  阅读(36)  评论(0编辑  收藏  举报