题目大意就是求 a^x = b(mod c) 中的x
用一般的baby step giant step 算法会超时
这里参考的是http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4
map平衡树查找值
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #include <map> 6 using namespace std; 7 #define ll long long 8 9 int q_pow(int a , int b , int mod) 10 { 11 ll ans = 1; 12 while(b) 13 { 14 if(b&1) ans =((ll)ans*a)%mod; 15 a = ((ll)a*a)%mod; 16 b>>=1; 17 } 18 return ans; 19 } 20 21 int gcd(int a , int b) 22 { 23 if(b == 0)return a; 24 else return gcd(b,a%b); 25 } 26 27 int ex_gcd(int a , int &x , int b , int &y) 28 { 29 if(b == 0){ 30 x=1 , y=0; 31 return a; 32 } 33 int ans = ex_gcd(b , x , a%b , y); 34 int t = x; 35 x=y , y = t-a/b*y; 36 return ans; 37 } 38 39 int inv(int a , int b , int mod) 40 { 41 int x , y , d; 42 d = ex_gcd(a , x , mod , y); 43 int e = (ll)x*b%mod; 44 return e<0?e+mod:e; 45 } 46 47 int BabyStep(int A,int B,int C){ 48 map<int,int> Hash; 49 ll buf=1%C,D=buf,K; 50 int i,d=0,tmp; 51 for(i=0;i<=100;buf=buf*A%C,++i) 52 if(buf==B) return i; 53 while((tmp=gcd(A,C))!=1) 54 { 55 if(B%tmp)return -1; 56 ++d; 57 C/=tmp; 58 B/=tmp; 59 D=D*A/tmp%C; 60 } 61 Hash.clear(); 62 int M=(int)ceil(sqrt((double)C)); 63 for(buf=1%C,i=0;i<=M;buf=buf*A%C,++i) 64 if(!Hash.count((int)buf))Hash[(int)buf]=i; 65 for(i=0,K=q_pow((ll)A,M,C);i<=M;D=D*K%C,++i) 66 { 67 tmp=inv(D,B,C); 68 if(tmp>=0&&Hash.count(tmp))return i*M+Hash[tmp]+d; 69 } 70 return -1; 71 } 72 int main() 73 { 74 // freopen("a.in" ,"r" , stdin); 75 int k , p , n; 76 while(scanf("%d%d%d" , &k , &p , &n) == 3) 77 { 78 if(n>=p){ 79 puts("Orz,I can’t find D!"); 80 continue; 81 } 82 int ans = BabyStep(k , n , p); 83 if(ans == -1) puts("Orz,I can’t find D!"); 84 else printf("%d\n" , ans); 85 } 86 return 0; 87 }