bsgs算法总结

bsgs算法总结


北上广深算法

BS高神算法

访问巨佬yyb的博客

现在要球解关于\(x\)的方程\(y^x\equiv z\ (\mod p\ )\)

然后\(\gcd(y,p)=1\)

\(x\)写成\(x=am-b\)的形式

\(y^{am}\equiv z\times y^b\ (\mod p\ )\)

\(b\)的取值只有\([0,m)\),然后可以算出来每一个取值后的结果,存在一个hash表里面

再枚举左边\(a\)判等,复杂度\(O(\max(m,p/m))\)

显然,取\(m=\sqrt p\)最优了

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<map>
#include<cmath>
#define il inline
#define rg register
#define vd void
#define sta static
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
ll y,z,p;
il ll pow(ll x,ll y){
    ll ret=1;
    while(y){
        if(y&1)ret=ret*x%p;
        x=x*x%p;y>>=1;
    }return ret;
}
il ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
std::map<ll,ll>yyb;
int main(){
#ifdef xzz
    freopen("calc.in","r",stdin);
    freopen("calc.out","w",stdout);
#endif
    int T=gi(),k=gi();
    while(T--){
        y=gi(),z=gi(),p=gi();
        if(k==1)printf("%lld\n",pow(y,z));
        else if(k==2){
            z%=p;
            ll d=(y%p)?1:p;
            if(z%d){puts("Orz, I cannot find x!");goto facai;}
            else printf("%lld\n",z*pow(y,p-2)%p);
        }else{
            if(y%p){
                y%=p,z%=p;
                if(z==1)
                    if(y==0){puts("Orz, I cannot find x!");goto facai;}
                    else{puts("0");goto facai;}
                ll m=sqrt(p)+1;yyb.clear();
                for(rg ll i=0,x=z%p;i<m;++i,x=x*y%p)yyb[x]=i;
                for(rg ll i=1,x=pow(y,m),t=x;i<=m+1;++i,t=t*x%p){
                    if(yyb.find(t)==yyb.end())continue;
                    printf("%lld\n",i*m-yyb[t]);
                    goto facai;
                }
                puts("Orz, I cannot find x!");
            }else puts("Orz, I cannot find x!");
          facai:;
        }
    }
    return 0;
}

还有个天坑扩展BSGS

待填

posted @ 2018-05-01 11:40  菜狗xzz  阅读(276)  评论(0编辑  收藏  举报