BZOJ4128 Matrix
题目描述:
给定矩阵A,B和模数p,求最小的x满足 A ^ x = B ( mod p)。(p是质数)
题解:
同样是BSGS,只是这道题放在了矩阵上。
其实并不需要矩阵求逆,将BSGS原理中的i * m + j 改为 i * m - j即可。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define ll long long int n,p; struct matrix { int s[80][80]; void read() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&s[i][j]); } void init() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) s[i][j]=(i==j); } int hs() { int ret = 0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) ret+=s[i][j]*(i+j)%p; ret%=p; } return ret; } }A,B,M[250]; matrix operator * (matrix &a,matrix &b) { matrix ret; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { ret.s[i][j]=0; for(int k=1;k<=n;k++) ret.s[i][j]=(ret.s[i][j]+a.s[i][k]*b.s[k][j]%p)%p; } return ret; } bool operator == (matrix &a,matrix &b) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a.s[i][j]!=b.s[i][j]) return 0; return 1; } int hed[20050],cnt; struct EG { int to,nxt; }e[250]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int find(matrix &a) { int now = a.hs(); for(int j=hed[now];j;j=e[j].nxt) if(M[e[j].to]==a) return e[j].to; return -1; } void BSGS() { M[0]=B; ae(M[0].hs(),0); int m = (int)sqrt(p); matrix MM; MM.init(); for(int i=1;i<=m;i++) { M[i]=A*M[i-1]; MM=MM*A; if(find(M[i])==-1) { int now = M[i].hs(); ae(now,i); } } matrix u; u.init(); for(int i=1;i<=m+2;i++) { u=u*MM; int ans = find(u); if(ans!=-1) { ans=m*i-ans; printf("%d\n",ans); break; } } } int main() { scanf("%d%d",&n,&p); A.read(); B.read(); BSGS(); return 0; }