扩展BSGS(学习笔记)

洛咕

题意:已知a,p,b,求满足\(a^x≡b(\mod p)\)的最小的自然数x(p不一定是质数).

当p是质数的时候,我们可以直接用普通的BSGS解决.而本题中p不一定是质数,就需要用到扩展的BSGS了.

大佬谈扩展BSGS

#include<bits/stdc++.h>
#define LL long long
using namespace std;
struct su{
    int x,y,p;
}b[72727];
int tot,head[72727];
inline int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
inline int gcd(int a,int b){
    if(b==0)return a;
    return gcd(b,a%b);
}
inline int ksm(LL x,int y,int p){
    int cnt=1;
    while(y){
        if(y&1)cnt=(cnt*x)%p;
        x=(x*x)%p;y>>=1;
    }
    return cnt;
}
inline void hash(int x,int y){
    b[++tot].x=x;b[tot].y=y;y%=72727;
    b[tot].p=head[y];head[y]=tot;
}
inline int BSGS(int x,int y,int p,int ex){
    int z=sqrt(p)+1;LL sx=1,sy;
    for(int i=0;i<z;++i){
		hash(i,sx*y%p);
		sx=sx*x%p;
    }
    sy=sx*ex%p;//唯一的改动,这里需要乘ex
    for(int i=1;i<=z;++i,sy=sy*sx%p)
        for(int j=head[sy%72727];j;j=b[j].p)
            if(b[j].y==sy)return i*z-b[j].x;
    return -1;
}
inline int EX_BSGS(int a,int b,int p){
    if(b==1)return 0;//特判b=1的情况
    LL c=1,z,d;int k=0;
    while(1){
        d=gcd(a,p);
        if(d==1)break;//a,p已经互质了就break掉
        if(b%d)return -1;//d无法整除y,方程无解
        ++k;c=c*(a/d)%p;
//k记录除了多少次,c表示的是方程的通解
        b/=d;p/=d;//利用上述同余性质
        if(c==b)return k;
    }
    z=BSGS(a,b,p,c);
    return z==-1?z:z+k;
}

int main(){
    while(1){
		int n=read(),mod=read(),m=read();tot=0;
		if(!n&&!m&&!mod)break;
        for(int i=0;i<72727;i++)head[i]=0;
//多组数据初始化
        int ans=EX_BSGS(n%mod,m%mod,mod);
        if(ans==-1)puts("No Solution");
        else printf("%d\n",ans);
    }
    return 0;
}

posted on 2019-04-09 22:17  PPXppx  阅读(106)  评论(0编辑  收藏  举报