BSGS algorithm (Baby Steps Giant Steps algorithm, Stride step algorithm, northward wide-depth algorithm, BA Shan-furious algorithm)
Applicable issues
For the equation:
$ $x ^y=z (mod_p) $$
Known x,z,p,p as prime numbers;
Solving a minimum nonnegative integer y;
There is a Y, which belongs to [0,p-2] (Fermat theorem)
So there's a clumsy way to enumerate Y.
Enumeration Y, desired efficiency: O (P)
Seek an optimization:
For a variant:
Set: $ $y =i\sqrt{p}-j$$
Then $ $x ^{i\sqrt{p}-j}=z (mod_p) $$
This variant is intended to take y apart.
Enumerates y, becomes an enumeration, i,j;
I between 1~$\sqrt{p}$, J between 0~$\sqrt{p}$
(The root of the i,j, in fact, the range of large can be larger-as long as the guaranteed Y is not less than 0)
Enumeration (I,J), expected efficiency: $O (\SQRT{P}*\SQRT{}P) $
No optimization in nature
Then variant:
$ $x ^{i\sqrt{p}}=z*x^{j} (mod_p) $$
-this variant is meant to actually separate y into two parts.
Enumeration J, the right of the equal sign of the modulo after the hash_table, at this time the same number only the maximum J value;
From small to large enumeration I, computes the left of the equal sign modulo, query hash_table, the first successful query of I, and its corresponding j, composed of $i\sqrt{p}-j$ is the smallest y,
Expected efficiency: $O (\sqrt{p}*t (hash)) $
Excellent efficiency, BA Shan the BSGS algorithm, this is the case;
Examples:
[SDOI2011] Calculator
Code:
#include <cstring>#include<cstdio>#include<cmath>#defineLL Long LongConst intss=999983; using namespacestd;inthash_tab[1000000],tot;structss{intNu,next,j;} data[1000000];voidWork ();voidWork1 ();voidWork2 ();voidWork3 (); ll Sqr (LL,int );intHashint,int,int ); LL z,y,p;BOOLFlag;intMain () {work ();}voidWork () {intt,k; scanf ("%d%d",&t,&K); while(t--) {scanf ("%lld%lld%lld",&y,&z,&p); if(k==1) Work1 (); if(k==2) Work2 (); if(k==3) Work3 (); }}voidWork1 () {inti,j,k; printf ("%lld\n", SQR (Y,z));}voidWork2 () {intans,less; if((! (y%p) &&z) | | ((y%p) &&!z)) {printf ("Orz, I cannot find x!\n");return; } printf ("%lld\n", SQR (y%p,p-2) *z%p);}voidWork3 () {Long Longysqrtp,sqrtp=ceil (sqrt (p)); memset (Hash_tab,0,sizeof(Hash_tab)); memset (data,0,sizeof(data)); Long LongL=1, r=z%p; inti,j; if((! (y%p) &&z) | | ((y%p) &&!z)) {printf ("Orz, I cannot find x!\n");return; } YSQRTP=SQR (Y,SQRTP); for(i=0; i<=sqrtp;i++) hash (r,i,0), (r*=y)%=p; for(i=1; i<=sqrtp;i++) {(L*=YSQRTP)%=p; if((J=hash (L,0,1))!=-1) {printf ("%lld\n", i*sqrtp-j); return ; }} printf ("Orz, I cannot find x!\n");} ll SQR (ll X,intN) {LL ret=1; while(n) {if(n&1) (ret*=x)%=p; (x*=X)%=p;n>>=1; } returnret;}intHashintNumintJintflag) { inttem; for(tem=hash_tab[num%ss];tem;tem=Data[tem].next) { if(data[tem].nu==num) { if(!flag&&j>data[tem].j) DATA[TEM].J=J; returnDATA[TEM].J; } if(!data[tem].next&&!flag) {Data[tem].next=++tot; DATA[TOT].J=J; Data[tot].nu=num; return-1; } } if(!flag) {Hash_tab[num%ss]=++tot; DATA[TOT].J=J; Data[tot].nu=num; } return-1;}
View Code
BSGS (Baby Steps Giant Steps) algorithm