zoukankan      html  css  js  c++  java
  • BSGS

    又称北上广深或拔山盖世

    运用了分块思想

    至于i,j的范围,还是要说一下

    i是1到sqrt的左闭右闭,因为是枚举一块一块的(大步),所以显然

    j是0到sqrt的左闭右开,因为零散的可有可无,而如果可以取到sqrt的话,为什么不并入i中呢?

    #include<bits/stdc++.h>
    #define LL long long 
    using namespace std;
    LL read()
    {
        LL f=1,x=0;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    map<LL,LL>ma;
    LL p; 
    LL quick_pow(LL a,LL x)
    {
        LL ans=1;
        while(x)
        {
            if(x&1) ans=ans*a%p;
            a=a*a%p;
            x=x/2;
        }
        return ans%p;
    }
    int main()
    {
        p=read();LL Y=read(),Z=read();
        ma.clear();
        if(Y==1)
        {
            printf("0
    ");
            return 0;
        } 
        int ans=-1,m=sqrt(p)+1;
        int tmp=Z;
        for(int i=0;i<m;++i)//小步 
        {
            ma[tmp]=i;
            tmp=1LL*tmp*Y%p;
        }
        int t=quick_pow(Y,m);
        tmp=1;
        for(int i=1;i<=m;++i)//大步 
        {
            tmp=1LL*tmp*t%p; 
            if(ma.count(tmp))
            {
                printf("%lld
    ",i*m-ma[tmp]);
                return 0;
            }
        }
        printf("no solution");
    }
    BSGS

    扩展BSGS

    模数不为质数的情况

    那我们就可以一直同除gcd,直到A,C互质

    具体看代码

    //a=b(mod p) ---> a/c=b/c(mod p/c)
    void exbsgs(LL A,LL B,LL C)
    {
        ma.clear();
        if(B==1){printf("0
    "); return;}
        int k=0;LL tmp=1;
        while(1)
        {
            LL d=gcd(A,C);
            if(d==1)break;
            if(B%d) printf("Math Error
    ");return;
            B/=d;C/=d;
            tmp=tmp*(A/d)%C;//注意A不要像B,C那样除d,因为求的是A^x 
            k++;
            if(tmp==B){printf("%d
    ",k);return;}//因为小于了k的判不到,在这里判 
        }
        LL m=sqrt(C)+1;
        tmp=B;
        for(int i=0;i<m;++i)
        {
            ma[tmp]=i;
            tmp=tmp*A%C;
        }
        LL t=quick(A,m,C);
        tmp=1;
        for(int i=1;i<=m;++i)
        {
            tmp=tmp*t%C;
            if(ma.count(tmp))
            {printf("%lld
    ",i*m-ma[tmp]+k);return;    } //记得加上k 
        }
        printf("Math Error
    ");return;
    }
    exBSGS
  • 相关阅读:
    11、sqlite
    10、正则
    9、bs4
    8、异常与import
    7、文件
    6、函数
    4、字典及集合
    3、元组
    1、python基本语法
    shell编程 15 --- shell 脚本调试技巧
  • 原文地址:https://www.cnblogs.com/yyys-/p/11311989.html
Copyright © 2011-2022 走看看