每次把gcd(a,c)提到前面,直到a,c互质,然后就是普通BSGS了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #define LL long long using namespace std; struct hashtable{ static const int N=577399; int tot,hash[N+10],key[N+5],nxt[N+5],w[N+5]; void clear() { tot=0; memset(hash,0,sizeof hash);memset(w,0,sizeof w); memset(nxt,0,sizeof nxt);memset(key,0,sizeof key); } void add(int x,int y) { key[++tot]=y;nxt[tot]=hash[x]; hash[x]=tot;w[tot]=0x7fffffff; } bool find(int y) { int x=y%N; for (int i=hash[x];i;i=nxt[i]) if (y==key[i]) return 1; return 0; } int& operator [] (int y) { int x=y%N; for (int j=hash[x];j;j=nxt[j]) if (y==key[j]) return w[j]; add(x,y);return w[tot]; } }f; int gcd(int x,int y){return y==0?x:gcd(y,x%y);} int exgcd(int a,int b,int &x,int &y){ if(b==0){x=1;y=0;return a;} int gcd=exgcd(b,a%b,x,y); int t=x; x=y; y=t-(a/b)*x; return gcd; } int exbsgs(int a,int b,int c){ int g,d=1,num=0,m,now=1; while((g=gcd(a,c))>1){ if(b%g!=0) return -1; b/=g; c/=g; d=((LL)d*(a/g))%c; num++; } m=(int)ceil(sqrt((double)c));now=1;f.clear(); for(int i=0;i<m;i++){ f[now]=min(f[now],i); now=((LL)now*a)%c; } for(int i=0;i<=m;i++){ int x,y,e=exgcd(d,c,x,y); x=((LL)x*b%c+c)%c; if(f.find(x))return i*m+f[x]+num; d=((LL)d*now)%c; } return -1; } int main(){ int a,b,c,ans; while(scanf("%d%d%d",&a,&c,&b)==3&&a!=0){ ans=exbsgs(a,b,c); if(ans==-1)printf("No Solution "); else printf("%d ",ans); } return 0; }