BSGS and ExBSGS

BSGS

Introduced

Solution to the Problem \ (X-\) equation,
\ [X-A ^ \ equiv B \ PMOD P \]
wherein \ (Gcd (A, P) = 1 \)

Solving

We make \ (X-I = * \ sqrt {P} -j \) , where \ (0 <= i, j
<= \ sqrt {P} \) is the original formula can be changed:
\ [X-A ^ \ equiv B \ PMOD P \]
\ [^ {A * I \ sqrt {P} -j} \ equiv B \ PMOD P \]
Since \ (Gcd (A, P) =. 1 \) , then the identity can change:
\ [a ^ {i * \
sqrt {P}} \ equiv B * a ^ j \ pmod P \] then we can first of all pre-treatment \ (a {I ^ * \ sqrt {P}} \) , save the hash table.
Re-enumeration \ (B * A ^ J \) , you can get to find the solution in the hash table.

Code

int quick_Pow(int x,int y,int p){
    if(y==0)return 1;
    if(y==1)return x;
    if(y%2)return 1ll*x*quick_Pow(1ll*x*x%p,y/2,p)%p;
    return quick_Pow(1ll*x*x%p,y/2,p);
}
void BSGS(int x,int y,int p){
    x%=p;y%=p;
    if(x==0&&y!=0){puts("-1");return ;}
    if(x==0&&y==0){puts("1");return ;}
    if(y==1){puts("0");return ;}
    int st=int(sqrt(p))+1;Mp.clear();
    for(int i=1,rt=1;i<=st;i++,rt=(1ll*rt*x)%p)Mp[rt]=i;
    int sum=quick_Pow(x,st,p);
    for(int i=1,rt=1;i<=st;i++){
        rt=(1ll*rt*sum)%p;
        if(Mp[rt]){
            printf("%d\n",i*st-Mp[rt]);
            return ;
        }
    }
    puts("-1");
}

ExBSGS

Introduced

Solution to the Problem \ (X-\) equation,
\ [X-A ^ \ equiv B \ PMOD P \]
wherein \ (Gcd (A, P) \) No special conditions.

Because of \ (Gcd (A, P) \) may not \ (1 \) , so \ (A \) on \ (P \) may no inverse element.
It can not be solved by a general BSGS.

Solving

We set \ (D = Gcd (A, P) \) ,
it is clear that there are \ (\ frac {A} {
D} \ equiv 1 \ pmod P \) is the original formula \ [A ^ X \ equiv B \ pmod P \]
may be constant deformation such as \ [A ^ {X-1
} \ cdot \ frac {A} {D} \ equiv \ frac {B} {D} \ pmod {\ frac {P} {D}} \] and because \ (Gcd (\ FRAC {A} {D}, \ FRAC {P} {D}) =. 1 \) , there are
\ [A ^ {X-1 } \ equiv \ frac {B} {D} \ cdot ({\ frac {A
} {D}}) ^ {- 1} \ pmod {\ frac {P} {D}} \] at this time, \ (\ frac {P} { D} \) is quite to the new \ (P \) values, \ (\ FRAC {B} {D} \ CDOT ({\ FRAC} {a} {D}) ^ {-}. 1 \) is equivalent to the new \ (B \ ) value,
it can go on like this recurrence. (Note: the next \ (D \) are novel \ (P \) values \ (A \) a \ (Gcd \) )

Consider boundary conditions:
①: If the current \ (. 1 D = \) , the problem is converted into a common BSGS.
②: If \ (B \) is equal to \ (1 \) , and the iteration to \ (Ans \) is \ (1 \) .
③: If \ (D \ Not | B \) , i.e. \ (D \) is not \ (B \) factor, the \ (\ frac {B} { D} \) does not make sense, no solution.

In summary, the solution.

And examples of code

Plate problem
that Italy: seeking to satisfy \ (A ^ X \ equiv B \ pmod {P} \) is the smallest integer \ (X-\)

#include<map>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<tr1/unordered_map>
using namespace std;
#define LL long long
tr1::unordered_map<LL,int>Mp;
LL Gcd(LL x,LL y){
    if(x==0)return y;
    return Gcd(y%x,x);
}
LL quick_Pow(LL x,LL y,LL p){
    if(y==0)return 1;
    if(y==1)return x;
    if(y%2)return x*quick_Pow(x*x%p,y/2,p)%p;
    return quick_Pow(x*x%p,y/2,p);
}
int ExBSGS(int x,int y,int p){
    if(y==1)return 0;//特判解为0的情况.
    LL k=0,a=1;
    while(1){
        int d=Gcd(x,p);if(d==1)break;
        if(y%d)return -1;
        y/=d;p/=d;k++;a=(1ll*a*x/d)%p;
        if(a==y)return k;//同特判.
    }Mp.clear();
    LL st=int(sqrt(p))+1,sum=quick_Pow(x,st,p);
    for(LL i=0,rt=y;i<=st;i++,rt=(1ll*rt*x)%p)Mp[rt]=i+1;
    for(LL i=1,rt=(a*sum)%p;i<=st;i++,rt=(1ll*rt*sum)%p){//不将求解中的A/D移项.
        if(!Mp[rt])continue;
        return 1ll*i*st-(Mp[rt]-1)+k;
    }
    return -1;
}
int A,B,C;
int main(){
    while(~scanf("%d%d%d",&A,&B,&C)&&A){
        int Ans=ExBSGS(A,C,B);
        if(Ans!=-1)printf("%d\n",Ans);
        else puts("Orz,I can’t find D!");
    }
}

Note: in general, given the subject A, B, C are positive integers.

Guess you like

Origin www.cnblogs.com/ftotl/p/11621342.html