BSGS算法学习笔记( [TJOI2007]可爱的质数)

版权声明:LeoJAM Presents https://blog.csdn.net/fcb_x/article/details/82077579

最害怕不会的东西终于学了

BSGS算法 Baby_Step_Giant_step算法(北上广深新一线算法或者拔山盖世算法)

是解决离散对数问题的利器

思路:不妨设L=i*m-j

且 m=ceil(sqrt(P))

在这一顿骚操作后

原式变为:B^{i*m}\equiv N*B^{j} (mod P)

由于j小于m所以预处理右边是O(sqrt(N))

右边枚举i不大于m

综上这是一个根号算法解决了

离散对数问题最小解的方法

#include<bits/stdc++.h>
using namespace std;
typedef int INT;
#define int long long
int b,p,n;
map<int,int> mmp;
inline int quick_pow(int x,int k){
    int ret=1;
    while(k){
        if(k%2==1){
            ret=ret*x%p;
        }
        x=x*x%p;
        k/=2;
    }
    return ret;
}
INT main(){
//	freopen("test.in","r",stdin);
    cin>>p>>b>>n;
    if(b%p==0){
        cout<<"no solution";
        return 0;
    }
    int m=ceil(sqrt(p));
    mmp[n%p]=0;
    for(int i=1;i<=m;i++){
        mmp[quick_pow(b,i)*n%p]=i;
    }	
    int t=quick_pow(b,m),ans=1;
    for(int i=1;i<=m;i++){
        ans=ans*t%p;
        if(mmp[ans]){
            int key=i*m-mmp[ans];
            cout<<((key%p)+p)%p;
            return 0;
        }
    }
    cout<<"no solution";
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/82077579