【题解】【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就会找不到目标,原因不明
Created: 2021-07-16 周五 19:54