嗯哼大步小步法。
一个非常暴力的想法.
注意到如果设C = ⌈√P⌉,那么任何一个数都可以写
成a1 * C + b1的形式,其中a1, b1 都< C.
那么预处理出A^i*C的值.然后在询问时枚举b1.
A^a1*C-b1 = B,A^a1*C = B * A^b1.
把A^b1乘一下,再去hash表里查找是否有对应的值即可.
复杂度为O(√P)
//POJ 2417
1 #include<cstdlib> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 #include<map> 7 #include<cmath> 8 using namespace std; 9 typedef long long ll; 10 map<ll,int>mmp; 11 int qmod(ll a,ll b,ll p) 12 { 13 ll ans=1; 14 while(b) 15 { 16 if(b&1)ans=ans*a%p; 17 a=a*a%p;b>>=1; 18 } 19 return ans; 20 } 21 int main() 22 { 23 ll p,a,b; 24 while(~scanf("%lld%lld%lld",&p,&a,&b)) 25 { 26 mmp.clear(); 27 if(a%p==0) 28 { 29 puts("no solution"); 30 continue; 31 } 32 bool flag=0; 33 ll ans=0; 34 int c=ceil(sqrt(p)); 35 for(int i=0;i<=c;++i) 36 { 37 if(i==0) 38 { 39 ans=b%p;mmp[ans]=i;continue; 40 } 41 ans=ans*a%p; 42 mmp[ans]=i; 43 } 44 ll tmp=qmod(a,c,p);ans=1; 45 for(int i=1;i<=c;++i) 46 { 47 ans=ans*tmp%p; 48 if(mmp[ans]) 49 { 50 tmp=i*c-mmp[ans]; 51 printf("%d\n",(tmp%p+p)%p); 52 flag=1; 53 break; 54 } 55 } 56 if(!flag)puts("no solution"); 57 } 58 return 0; 59 }