学习一个大步小步求离散对数

来源:互联网 发布:linux安装suse11 编辑:程序博客网 时间:2024/06/05 22:29

Hash 实现
idy的板子十分的漂亮

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define S 100007struct Hash_Map{    int head[S],nxt[S],dest[S][2],tot;    void init()    {        memset(head,-1,sizeof(head));        tot=0;    }    void add(int a,int b)    {        int key=a%S;        for(int i=head[key];~i;i=nxt[i])            if(dest[i][0]==a) return;        dest[++tot][0]=a;        dest[tot][1]=b;        nxt[tot]=head[key];        head[key]=tot;    }    int find(int a)    {        int key=a%S;        for(int i=head[key];~i;i=nxt[i])            if(dest[i][0]==a) return dest[i][1];        return -1;    }}hash;void exgcd(int a,int b,int &d,int &x,int &y){    if(b==0){d=a;x=1;y=0;}    else    {        int xx,yy;        exgcd(b,a%b,d,xx,yy);        x=yy;        y=xx-(a/b)*yy;    }}int inverse(int a,int m){    int d,x,y;    exgcd(a,m,d,x,y);    return (x%m+m)%m;}int ind(int a,int b,int m) {    int c=(int)ceil(sqrt(m) + 1);    hash.init();    int cur=1;    for(int i=0;i<c;i++,cur=(1LL*cur*a)%m)     {        hash.add(cur,i);        if(b==cur) return i;    }    int base=inverse(cur,m);        cur=1LL*b*base%m;       for(int i=c;i<=m;i+=c,cur=(1LL*cur*base)%m)     {        int j=hash.find(cur);        if(j!=-1) return c+j;    }    return -1;}int main(){    int a,b,m;    scanf("%d%d%d",&a,&b,&m);    printf("%d\n",ind(a,b,m));}
原创粉丝点击