• BSGS & exBSGS


    BSGS 

    BSGS 用于当gcd(A,p)=1时,求方程的解。

    由费马定理可知,当gcd(A,p)=1,且p为素数时,有所以得到

    ,x=am-b,,得到

    通过枚举用hash维护任意一侧,再枚举另一侧,判断是否在hash,若在则答案为am-b。

    例:poj 2417 Discrete Logging

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<cmath>
    using namespace std;
    long long quick(long long a,long long b,long long p);
    int main()
    {
      int i,f;
      long long s,t,A,B,p,m;
      while(~scanf("%lld%lld%lld",&p,&A,&B))
      {
        map<long long,long long> lmapl;
        f=0;m=ceil(sqrt(p));
        for(i=1;i<=m;i++)
        {
          B=B*A%p;
          lmapl[B]=i;
        }
        t=quick(A,m,p);
        for(i=1,s=1;i<=m;i++)
        {
          s=s*t%p;
          if(lmapl[s])
          {
           printf("%lld
    ",i*m-lmapl[s]);
           f=1;
           break;
          }
        }
        if(!f) printf("no solution
    ");
      }
      return 0;
    }
    long long quick(long long a,long long b,long long p)
    {
      long long ans=1;
      while(b)
      {
        if(b&1) ans=ans*a%p;
        b>>=1;
        a=a*a%p;
      }
      return ans%p;
    }
    View Code

    exBSGS

    BSGS只能解决gcd(A,p)=1的情况,而通过exBSGS可以解决更一般的情况(不互质的情况)。

    ,得到,令d=gcd(A,p),通过同余定理可以得到(如果B%d!=0,则无解),通过这种方式一直往下迭代,直到 d=1 ,此时得到

     ,k为迭代次数,得到再通过BSGS求解,最后答案加上k。

    int exbsgs(int a,int b,int p)
    {
        if (b==1||p==1)return 0;     //特殊情况,x=0时最小解
        int g=gcd(a,p),k=0,na=1;
        while (g>1)
        {
            if (b%g!=0)return -1;    //无法整除则无解
            k++;b/=g;p/=g;na=na*(a/g)%p;
            if (na==b)return k;   //na=b说明前面的a的次数为0,只需要返回k
            g=gcd(a,p); 
        }
        int f=bsgs(a,b*inv(na,p)%p,p);
        if (f==-1)return -1;
        return f+k;
    }

    例:poj 3243  Clever Y

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<cmath>
    #include<cstring>
    using namespace std;
    struct HashTable
    {
      static const int MOD=99901,MAXN=200005;
      long long dat[MAXN],nxt[MAXN],head[MAXN],id[MAXN],cnt;
      void clear() 
      {
        memset(head,-1,sizeof(head));
        memset(nxt,0,sizeof(nxt));
        cnt=0;
      }
      void insert(long long x, long long y)
      {
        long long tmp=x%MOD;
        for(int i=head[tmp];i!=-1;i=nxt[i]) 
          if(dat[i]==x) 
           {
             id[i]=y; 
             return;
           }
        dat[++cnt]=x;id[cnt]=y;
        nxt[cnt]=head[tmp];head[tmp]=cnt;
      }
      long long query(long long x)
      {
        long long tmp=x%MOD;
        for(int i=head[tmp];i!=-1;i=nxt[i]) 
        {
          if(dat[i]==x) 
            return id[i];
        }
        return -1;
      }
    }Hash;
    long long quick(long long a,long long b,long long p);
    long long bsgs(long long a,long long b,long long p,long long f);
    long long exbsgs(long long a,long long b,long long p);
    long long gcd(long long x,long long y);
    int main()
    {
      long long a,p,b,ans;
      while(scanf("%lld%lld%lld",&a,&p,&b))
      {
        if(!a&&!p&&!b) break;
        ans=exbsgs(a,b,p);
        if(ans!=-1) printf("%lld
    ",ans);
        else printf("No Solution
    ");
      }
      return 0;
    }
    long long gcd(long long x,long long y)
    {return y?gcd(y,x%y):x;}
    long long quick(long long a,long long b,long long p)
    {
      long long ans=1;
      while(b)
      {
        if(b&1) ans=ans*a%p;
        b>>=1;
        a=a*a%p;
      }
      return ans;
    }
    long long exbsgs(long long a,long long b,long long p)
    {
      Hash.clear();
      if(b==1||p==1) return 0;
      long long d=gcd(a,p),k=0,na=1,ans;
      while(d!=1)
      {
       if(b%d) return -1;
       k++;b/=d;p/=d;na=na*(a/d)%p;
       if(na==b) return k;
       d=gcd(a,p);
      }
      ans=bsgs(a,b,p,na);
      return ans==-1?-1:ans+k;
    }
    long long bsgs(long long a,long long b,long long p,long long f)
    {
      int i;
      long long m=ceil(sqrt(p)),s,t;
      for(i=1;i<=m;i++)
      {
        b=b*a%p;
        Hash.insert(b, i);
      }
      t=quick(a,m,p);
      for(i=1,s=f;i<=m;i++)
      {
       s=s*t%p;
       if(Hash.query(s)!=-1) return i*m-Hash.query(s);
      }
      return -1;
    }
    View Code
    本博客仅为本人学习,总结,归纳,交流所用,若文章中存在错误或有不当之处,十分抱歉,劳烦指出,不胜感激!!!
  • 相关阅读:
    Python写出LSTM-RNN的代码
    TensorFlow 实现 RNN 入门教程
    RNN与应用案例:注意力模型与机器翻译
    RNN入门
    内积(又名点积)
    词袋模型(BOW, bag of words)
    softmax
    Dropout
    随机梯度下降法
    L1范式和L2范式
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/11452707.html
Copyright © 2020-2023  润新知