BSGS及扩展BSGS模板

BSGS

#include <iostream>//poj2417
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;
const int maxint=((1<<30)-1)*2+1;

int A,B,C;
struct Hashmap{
    static const int Ha=999917,maxe=46340;
    int E,lnk[Ha],son[maxe+5],nxt[maxe+5],w[maxe+5];
    int top,stk[maxe+5];
    void clear() {E=0;while(top) lnk[stk[top--]]=0;}
    void Add(int x,int y){son[++E]=y;nxt[E]=lnk[x];w[E]=maxint;lnk[x]=E;}
    bool count(int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return true;
        return false;
    }
    int& operator [] (int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return w[j];
        Add(x,y);stk[++top]=x;return w[E];
    }
};
Hashmap f;


int exgcd(int a,int b,int &x,int &y)
{
    if(!b) {x=1;y=0;return a;}
    int r=exgcd(b,a%b,x,y),t=x;x=y;y=t-(a/b)*y;
    return r;
}

int BSGS(int A,int B,int C)
{
    if(C==1) if(!B) return A!=1; else return -1;
    if(B==1) if(A) return 0; else return -1;
    if(A%C==0) if(!B) return 1;else return -1;
    int m=ceil(sqrt(C)),D=1,Base=1;f.clear();
    for(int i=0;i<=m-1;i++)//先把A^j存进哈希表
    {
        f[Base]=min(f[Base],i);
        Base=((ll)Base*A)%C;
    }
    for(int i=0;i<=m-1;i++)
    {
        int x,y,r=exgcd(D,C,x,y);
        x=((ll)x*B%C+C)%C;//扩欧求A^j
        if(f.count(x)) return i*m+f[x];//找到解
        D=((ll)D*Base)%C;
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d%d",&C,&A,&B))
    {
        int ans=BSGS(A,B,C);
        if(ans==-1) printf("no solution\n");
        else printf("%d\n",ans);
    }
    return 0;
}

扩展BSGS

#include <iostream>//poj3243
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;
const int maxint=((1<<30)-1)*2+1;

int A,B,C;
struct Hashmap{
    static const int Ha=999917,maxe=46340;
    int E,lnk[Ha],son[maxe+5],nxt[maxe+5],w[maxe+5];
    int top,stk[maxe+5];
    void clear() {E=0;while(top) lnk[stk[top--]]=0;}
    void Add(int x,int y){son[++E]=y;nxt[E]=lnk[x];w[E]=maxint;lnk[x]=E;}
    bool count(int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return true;
        return false;
    }
    int& operator [] (int y)
    {
        int x=y%Ha;
        for(int j=lnk[x];j;j=nxt[j])
            if(y==son[j]) return w[j];
        Add(x,y);stk[++top]=x;return w[E];
    }
};
Hashmap f;

int gcd(int a,int b){
    if(!b) return a;
    else return gcd(b,a%b);
}

int exgcd(int a,int b,int &x,int &y)
{
    if(!b) {x=1;y=0;return a;}
    int r=exgcd(b,a%b,x,y),t=x;
    x=y;y=t-(a/b)*y;
    return r;
}

int exBSGS(int A,int B,int C)
{
    if(C==1) if(!B) return A!=1;else return -1;
    if(B==1) if(A) return 0;else return -1;
    if(A%C==0) if(!B) return 1;else return -1;
    int r,D=1,num=0;
    while((r=gcd(A,C))>1)
    {
        if(B%r) return -1;num++;
        B/=r;C/=r;D=((ll)D*A/r)%C;
    }
    for(int i=0,now=1;i<num;i++,now=((ll)now*A)%C)
    {
        if(now==B) return i;
    }
    int m=ceil(sqrt(C)),Base=1;f.clear();
    for(int i=0;i<=m-1;i++)
    {
        f[Base]=min(f[Base],i);
        Base=((ll)Base*A)%C;
    }
    for(int i=0;i<=m-1;i++)
    {
        int x,y,r=exgcd(D,C,x,y);
        x=((ll)x*B%C+C)%C;
        if(f.count(x)) return i*m+f[x]+num;
        D=((ll)D*Base)%C;
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d%d",&A,&C,&B))//A^y mod C=B
    {
        if(!A&&!B&&!C) break;
        int ans=exBSGS(A,B,C);
        if(ans==-1) printf("No Solution\n");
        else printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2018-10-14 14:16  Somnus、M  阅读(286)  评论(0编辑  收藏  举报