先奉上AC神的baby step giant step算法及其扩展介绍
两种不同的模板:
解 型如A^x=B(mod c)的最小解x
AC神版:
#include <iostream> #include <map> #include <cmath> #include <cstdio> using namespace std; typedef long long LL; const int maxn = 65535; struct hash { int a,b,next; } Hash[maxn << 1]; int flg[maxn + 66]; int top,idx; void ins(int a,int b) { int k = b & maxn; if(flg[k] != idx) { flg[k] = idx; Hash[k].next = -1; Hash[k].a = a; Hash[k].b = b; return ; } while(Hash[k].next != -1) { if(Hash[k].b == b) return ; k = Hash[k].next; } Hash[k].next = ++ top; Hash[top].next = -1; Hash[top].a = a; Hash[top].b = b; } int find(int b) { int k = b & maxn; if(flg[k] != idx) return -1; while(k != -1) { if(Hash[k].b == b) return Hash[k].a; k = Hash[k].next; } return -1; } int gcd(int a,int b) { return b?gcd(b,a%b):a; } int ext_gcd(int a,int b,int& x,int& y) { int t,ret; if (!b) { x=1,y=0; return a; } ret=ext_gcd(b,a%b,x,y); t=x,x=y,y=t-a/b*y; return ret; } int Inval(int a,int b,int n) { int x,y,e; ext_gcd(a,n,x,y); e=(LL)x*b%n; return e<0?e+n:e; } int pow_mod(LL a,int b,int c) { LL ret=1%c; a%=c; while(b) { if(b&1)ret=ret*a%c; a=a*a%c; b>>=1; } return ret; } int BabyStep(int A,int B,int C) { top = maxn; ++ idx; LL buf=1%C,D=buf,K; int i,d=0,tmp; for(i=0; i<=100; buf=buf*A%C,++i)if(buf==B)return i; while((tmp=gcd(A,C))!=1) { if(B%tmp)return -1; ++d; C/=tmp; B/=tmp; D=D*A/tmp%C; } int M=(int)ceil(sqrt((double)C)); for(buf=1%C,i=0; i<=M; buf=buf*A%C,++i)ins(i,buf); for(i=0,K=pow_mod((LL)A,M,C); i<=M; D=D*K%C,++i) { tmp=Inval((int)D,B,C); int w ; if(tmp>=0&&(w = find(tmp)) != -1)return i*M+w+d; } return -1; } int main() { int A,B,C; while(scanf("%d%d%d",&C,&A,&B)!=EOF) { B %= C; int tmp=BabyStep(A,B,C); if(tmp<0)puts("no solution"); else printf("%d\n",tmp); } return 0; }
#include <iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define N 100000 struct hashtable { int key[N]; int value[N]; void init() { for(int i=0;i<N;i++)key[i]=-1,value[i]=-1; } void insert(int k,int v) { int kk=k%N; while(key[kk]!=-1&&key[kk]!=k) kk=(kk+1)%N; key[kk]=k,value[kk]=v; } int find(int k) { int kk=k%N; while(key[kk]!=-1&&key[kk]!=k) kk=(kk+1)%N; return value[kk]; } }h; int baby_giant(int x,int k,int z) { x%=z,k%=z; int m=(int)ceil(sqrt(1.0*z)),pre=1; h.init();h.insert(k,0); for(int i=1; i<=m; i++) { pre=(1ll*pre*x)%z; h.insert((1ll*pre*k)%z,i); } for(int i=0,xm=pre,y=1;i*m<=z;i++) { int j=h.find(y); if(j>=0&&i*m-j>=0) return i*m-j; y=(1ll*y*xm)%z; } return -1; } int main() { // freopen("in","r",stdin); int b,n,p; while(scanf("%d%d%d",&p,&b,&n)!=EOF) { int ans=baby_giant(b,n,p); if(ans>=0)cout<<ans<<endl; else cout<<"no solution"<<endl; } return 0; }