Submit: 530 Solved: 279
Description
给定矩阵A,B和模数p,求最小的x满足 A^x = B (mod p)
Input
第一行两个整数n和p,表示矩阵的阶和模数,接下来一个n * n的矩阵A.接下来一个n * n的矩阵B
Output
输出一个正整数,表示最小的可能的x,数据保证在p内有解
Sample Input
2 7
1 1
1 0
5 3
3 2
1 1
1 0
5 3
3 2
Sample Output
4
HINT
对于100%的数据,n <= 70,p <=19997,p为质数,0<= A_{ij},B_{ij}< p
保证A有逆
数学 矩阵乘法 BSGS
矩阵上的BSGS,除了重载一堆东西简直烦以外,本质上还是一个BSGS。
好像有特殊的hash技巧可以让判重变得十分简便。
然而我选择了暴力
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<map> 9 using namespace std; 10 const int mxn=71; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 int n,P; 18 struct Mat{ 19 int a[mxn][mxn]; 20 friend Mat operator * (const Mat &x,const Mat &y){ 21 Mat res; 22 int i,j,k; 23 for(i=1;i<=n;i++) 24 for(j=1;j<=n;j++){ 25 res.a[i][j]=0; 26 for(k=1;k<=n;k++) 27 (res.a[i][j]+=x.a[i][k]*y.a[k][j])%=P; 28 } 29 return res; 30 } 31 friend bool operator < (const Mat &x,const Mat &y){ 32 for(int i=1;i<=n;i++) 33 for(int j=1;j<=n;j++) 34 if(x.a[i][j]^y.a[i][j]) 35 return (x.a[i][j]<y.a[i][j]); 36 return false; 37 } 38 friend bool operator == (const Mat &x,const Mat &y){ 39 for(int i=1;i<=n;i++) 40 for(int j=1;j<=n;j++) 41 if(x.a[i][j]^y.a[i][j])return 0; 42 return 1; 43 } 44 }a,b,c; 45 map<Mat,int>mp; 46 void Debug(Mat x){ 47 for(int i=0;i<=n;i++){ 48 for(int j=0;j<=n;j++)printf("%d ",x.a[i][j]); 49 printf(" "); 50 } 51 printf("fin "); 52 } 53 int main(){ 54 int i,j; 55 n=read();P=read(); 56 for(i=1;i<=n;i++) 57 for(j=1;j<=n;j++) 58 a.a[i][j]=read(); 59 for(i=1;i<=n;i++) 60 for(j=1;j<=n;j++) 61 b.a[i][j]=read(); 62 c=a; 63 int m=sqrt(P)+1; 64 for(i=1;i<=m;i++){ 65 Mat tmp=b*c; 66 if(!mp.count(tmp)){ 67 mp[tmp]=i; 68 } 69 if(i<m)c=c*a; 70 } 71 a=c; 72 int ans=0x3f3f3f3f; 73 for(i=m;i<=P;i+=m){ 74 if(mp.count(a)){ 75 ans=i-mp[a]; 76 break; 77 } 78 a=a*c; 79 } 80 printf("%d ",ans); 81 return 0; 82 }