求解 a^x≡b (mod c)
( x<c )
siz = sqrt( c )
a^( i*siz + j) ≡b (mod c)
a^j ≡ a^( - i* siz) *b (mod c)
枚举 j , 将 (j, a^j %c ) 存入map ;
枚举 i, 查询map的值 ( a^(-i *siz) *b %c
#include <iostream> #include <algorithm> #include <cstring> #include <unordered_map> #include <cmath> using namespace std; #define int long long #define INF 1e18 void gcd(int a,int b,int &d,int &x,int &y){ if(b==0){ d=a; x=1,y=0; return ; } gcd(b,a%b,d,y,x); y-=x*(a/b); } int BSGS(int A,int B,int C){ if(C==1){ if(!B) return A!=1; return -1; } if(B==1){ if(A) return 0; return -1; } if(A%C==0){ if(!B) return 1; return -1; } unordered_map<int,int> mp ; int siz=ceil(sqrt(C)); int D=1,s=1; // a^j %c for(int i=0;i<=siz-1;i++){ mp[s]=min(mp[s],i); s=(s*A)%C; } // a^(-i*siz)*b %c for(int i=0;i<=siz-1;i++){ int x,y; int g; gcd(D,C,g,x,y); x=(x*B%C+C)%C; if(mp.count(x)) return i*siz+mp[x]; D=(D*s)%C; } return -1; } signed main(){ int A,B,C; while(cin>>C>>A>>B){ int res=BSGS(A,B,C); if(res==-1) printf("no solution\n"); else printf("%lld\n",res); } }
手写hashmap
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define int long long #define INF 1e18 void gcd(int a,int b,int &d,int &x,int &y){ if(b==0){ d=a; x=1,y=0; return ; } gcd(b,a%b,d,y,x); y-=x*(a/b); } struct HashMap{//哈希表 static const int Hash=999917,maxn=46340; int num,link[Hash],son[maxn+5],next[maxn+5],w[maxn+5]; int top,Stack[maxn+5]; void clear(){//清空表 num=0; while(top) link[Stack[top--]]=0; } void add(int x,int y){//添加键值元素 son[++num]=y; next[num]=link[x]; w[num]=INF; link[x]=num; } bool count(int y){//判断表中是否有对应值 int x=y%Hash; for(int j=link[x];j;j=next[j]) if(y==son[j]) return true; return false; } int &operator [](int y){//获取键的对应值 int x=y%Hash; for(int j=link[x];j;j=next[j]) if(y==son[j]) return w[j]; add(x,y); Stack[++top]=x; return w[num]; } }mp ; int BSGS(int A,int B,int C){ if(C==1){ if(!B) return A!=1; return -1; } if(B==1){ if(A) return 0; return -1; } if(A%C==0){ if(!B) return 1; return -1; } mp.clear(); int siz=ceil(sqrt(C)); int D=1,s=1; // a^j %c for(int i=0;i<=siz-1;i++){ mp[s]=min(mp[s],i); s=(s*A)%C; } // a^(-i*siz)*b %c for(int i=0;i<=siz-1;i++){ int x,y; int g; gcd(D,C,g,x,y); x=(x*B%C+C)%C; if(mp.count(x)) return i*siz+mp[x]; D=(D*s)%C; } return -1; } signed main(){ int A,B,C; while(cin>>C>>A>>B){ int res=BSGS(A,B,C); if(res==-1) printf("no solution\n"); else printf("%lld\n",res); } }