【算法乱讲】BSGS

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\n",m*i+l);
65             return;
66         }
67     }
68     printf("no solution\n");
69 }
70 int main(){
71     while(scanf("%lld%lld%lld",&P,&A,&B)!=EOF){
72         init();
73     }
74     return 0;
75 }

posted @ 2016-09-02 23:49  ExiledPoet  阅读(314)  评论(0编辑  收藏  举报