【算法乱讲】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 }
蜉蝣渴望着飞翔,尽管黄昏将至