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;
}

 

posted @ 2018-11-30 20:11  LiGuanlin  阅读(204)  评论(0编辑  收藏  举报