Description
Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that BL== N (mod P)
Input
Read several lines of input, each containing P,B,N separated by a space.
Output
For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".
Sample Input
5 2 1
5 2 2
5 2 3
5 2 4
5 3 1
5 3 2
5 3 3
5 3 4
5 4 1
5 4 2
5 4 3
5 4 4
12345701 2 1111111
1111111121 65537 1111111111
Sample Output
0
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587
显然,这是一道bsgs的裸题
那么bsgs是什么玩意呢,
我们先玩一玩式子
令 m=ceil(sqrt(p))设a^(m*i+j)=b(mod p)
显然 a^j*a^(m*i)=b(mod p)
a^j=b*a^(-m*i) (mod p)
因此,我们预处理所有可能的a^j丢进哈希表中然后我们枚举i,
看看有没有可能对应的j所以我们的算法时间复杂度为O(n^0.5)
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<iostream>
4 #include<string>
5 #include<string.h>
6 #include<algorithm>
7 #include<math.h>
8 #include<queue>
9 #include<map>
10 #include<vector>
11 #include<set>
12 #define il inline
13 #define re register
14 using namespace std;
15 typedef long long ll;
16 struct hash_set{
17 ll v[111111];
18 int next[111111],g[111111],w[111111],tot;
19 il void clear(){
20 memset(g,false,sizeof(g));tot=0;
21 }
22 il void insert(ll h,int f){
23 v[++tot]=h;
24 w[tot]=f;
25 next[tot]=g[h%100007];
26 g[h%100007]=tot;
27 }
28 il int find(ll h){
29 for(re int i=g[h%100007];i;i=next[i])
30 if(h==v[i]) return w[i];
31 return -1;
32 }
33 } p;
34 ll A,B,P,m,t,s;
35 il ll ksm(re ll base,re ll pow){
36 if(pow<0){
37 cout<<"-1";exit(0);
38 }
39 ll ans=1;
40 for(;pow;pow>>=1){
41 if(pow&1) ans=ans*base%P;
42 base=base*base%P;
43 }
44 return ans;
45 }
46 il ll rev(re ll a){
47 return ksm(a,P-2);
48 }
49 il void init(){
50 p.clear();
51 m=ceil(sqrt(P));t=1;
52 for(int i=0;i<m;i++){
53 if(p.find(t)<0) p.insert(t,i);
54 t=t*A%P;
55 }
56 //cout<<endl;
57 for(int i=0,l;i<=P/m;i++){
58 t=rev(ksm(A,m*i));
59 // cout<<t<<" "<<m*i<<" ";
60 s=t*B%P;
61 // cout<<s<<endl;
62 l=p.find(s);
63 if(l>=0){
64 printf("%lld
",m*i+l);
65 return;
66 }
67 }
68 printf("no solution
");
69 }
70 int main(){
71 while(scanf("%lld%lld%lld",&P,&A,&B)!=EOF){
72 init();
73 }
74 return 0;
75 }