题目其实很简单,BSGS可以一眼看出来,但这就需要矩阵求逆,然而我并不会。。。
于是发现了一种BSGS的非求逆方法,借此介绍一下。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
int n,P;
struct hp{
int num[71][71];
bool operator < (const hp& a)const
{
int i,j;
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
{
if (num[i][j]<a.num[i][j]) return true;
if (num[i][j]>a.num[i][j]) return false;
}
return false;
}
bool operator > (const hp& a)const
{
int i,j;
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
{
if (num[i][j]<a.num[i][j]) return false;
if (num[i][j]>a.num[i][j]) return true;
}
return false;
}
bool operator == (const hp& a)const
{
int i,j;
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
{
if (num[i][j]<a.num[i][j]) return false;
if (num[i][j]>a.num[i][j]) return false;
}
return true;
}
}a,b;
hp mult(hp a,hp b)
{
hp c;int i,j,k;
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
{
c.num[i][j]=0;
for (k=1;k<=n;++k)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j])%P;
}
return c;
}
int bsgs()
{
int i,j,m;
hp e,mi,xi;
map<hp,int>x;
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
e.num[i][j]=b.num[i][j];
m=(int)(sqrt(P)+0.5); x[e]=0;
for (i=1;i<=m;++i)
{
e=mult(e,a);
x[e]=i;
}
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
{
mi.num[i][j]=0;
if (i==j)
mi.num[i][j]=1;
}
for (i=1;i<=m;++i)
mi=mult(mi,a);
xi=mi;
for (i=1;i<=m;++i)
{
if (x.count(mi)) return i*m-x[mi];
mi=mult(mi,xi);
}
}
int main()
{
int i,j;
scanf("%d%d",&n,&P);
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
scanf("%d",&a.num[i][j]);
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
scanf("%d",&b.num[i][j]);
printf("%d\n",bsgs());
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/lcomyn/article/details/46714569