1 Accepted 8508K 391MS C++ 2004B
2 相比下边,,优化太多太多了。。。
3 /**
4 baby-step-giant-step 因为数据量太大,,自己写hash
5
6 **/
7 #include <iostream>
8 #include <cstdio>
9 #include <cmath>
10 #include <cstring>
11 using namespace std;
12 long long n,a,b;
13 const int maxn = 499991;
14 bool Hash[maxn];
15 long long idx[maxn];
16 long long val[maxn];
17
18 void ex_gcd(long long a,long long b,long long &x,long long &y){
19 if(b==0){
20 x=1;
21 y=0;
22 return ;
23 }
24 ex_gcd(b,a%b,x,y);
25 long long tmp = x-(a/b)*y;
26 x = y;
27 y = tmp;
28 }
29
30 long long euler(long long n){
31 long long i,tmp = n;
32 for(i=2;i*i<=n;i++)if(n%i==0){
33 tmp = tmp/i*(i-1);
34 while(n%i==0)
35 n = n/i;
36 }
37 if(n>1)
38 tmp = tmp/n*(n-1);
39 return tmp;
40 }
41
42 void Insert(long long id,long long num){
43 long long k = num%maxn;
44 while(Hash[k]&&val[k]!=num){
45 k++;
46 if(k==maxn) k = k-maxn;
47 }
48 if(!Hash[k]){
49 Hash[k] =1;
50 idx[k] = id;
51 val[k] = num;
52 }
53 }
54
55 long long found(long long num){
56 long long k = num%maxn;
57 while(Hash[k]&&val[k]!=num){
58 k++;
59 if(k==maxn) k = k-maxn;
60 }
61 if(!Hash[k]){
62 return -1;
63 }
64 return idx[k];
65 }
66
67 long long baby_step(long long a,long long b,long long n){
68 long long m = ceil(sqrt(euler(n)+0.5));
69 memset(Hash,false,sizeof(Hash));
70 memset(idx,-1,sizeof(idx));
71 memset(val,-1,sizeof(val));
72 long long d=1;
73 for(long long i=0;i<m;i++){
74 Insert(i,d);
75 d = d*a%n;
76 }
77 long long res =1;
78 long long x,y;
79 for(long long i=0;i<m;i++){
80 ex_gcd(res,n,x,y);
81 long long tmp = x*b%n;
82 tmp = (tmp%n+n)%n;
83 long long k = found(tmp);
84 if(k!=-1){
85 return (i)*m+k;
86 }
87 res = res*d%n;
88 }
89 return -1;
90 }
91
92 int main()
93 {
94 while(scanf("%I64d%I64d%I64d",&n,&a,&b)==3){
95 long long res = baby_step(a,b,n);
96 if(res==-1)
97 printf("no solution\n");
98 else
99 printf("%I64d\n",res);
100 }
101 return 0;
102 }
103
104 -----------------------------------分割线---------------------------------------
105 /**
106 高次方程。。。baby-step-giant-step 算法
107 Accepted 4592K4 516MS C++1104B
108 **/
109 #include <iostream>
110 #include <cstdio>
111 #include <math.h>
112 #include <map>
113 using namespace std;
114
115 long long powmod(long long a,long long b,long long n){
116 if(b==0)
117 return 1;
118 long long c =1;
119 while(b){
120 if(b&1)
121 c =c*a%n;
122 a =a*a%n;
123 b>>=1;
124 }
125 return c;
126 }
127
128 long long logmod(long long a,long long b,long long n){
129 long long m,v,e=1,i;
130 m = ceil(sqrt(n+0.5));
131 //cout<<(double)(n-1)*1.0/m<<endl;
132 //long long m_n = powmod(a,m,n);
133 v = powmod(a,n-1-m,n);
134 map<long long ,long long >x;
135 x.clear();
136 x[1] =m;
137 for(i=1;i<m;i++){
138 e = e*a%n;
139 if(!x[e]) x[e]=i;
140 }
141 for(i=0;i<m;i++){
142 if(x[b]){
143 long long num = x[b];
144 x.clear();
145 return i*m+(m==num?0:num);
146 }
147 b = b*v%n;
148 }
149 return -1;
150 }
151
152 int main()
153 {
154 long long a,b,n;
155 while(scanf("%I64d%I64d%I64d",&n,&a,&b)==3){
156 long long res = logmod(a,b,n);
157 if(res==-1)
158 printf("no solution\n");
159 else
160 printf("%I64d\n",res);
161 }
162 return 0;
163 }