POJ 2417 Discrete Logging 离散对数/BabyStep_GiantStep

来源:互联网 发布:淘宝上如何用微信支付 编辑:程序博客网 时间:2024/05/11 22:44

题意:BL == N (mod P),并且p是素数

题解:

#include<cstdio>#include<cmath>#include<cstring>using namespace std;#define lint  __int64#define MAXN 131071struct HashNode { lint data, id, next; };HashNode hash[MAXN<<1];bool flag[MAXN<<1];lint top;lint gcd ( lint a, lint b ){    return b ? gcd ( b, a % b ) : a;}lint ext_gcd ( lint a, lint b, lint& x, lint& y ){    lint t, ret;    if ( b == 0 )    {        x = 1, y = 0;        return a;    }    ret = ext_gcd ( b, a % b, x, y );    t = x; x = y; y = t - a / b * y;    return ret;}lint mod_exp ( lint a, lint b, lint n ){    lint ret = 1;    a = a % n;    while ( b >= 1 )    {        if ( b & 1 )            ret = ret * a % n;        a = a * a % n;        b >>= 1;    }    return ret;}void Insert ( lint index, lint num ){    lint k = num % MAXN;    if ( flag[k] == false )    {        flag[k] = true;        hash[k].id = index;        hash[k].data = num;        hash[k].next = -1;        return;    }    while ( hash[k].next != -1 )    {        if ( hash[k].data == num ) return;        k = hash[k].next;    }    if ( hash[k].data == num ) return;    hash[k].next = ++top;    hash[top].id = index;    hash[top].data = num;    hash[top].next = -1;}lint Find ( lint num ){    lint k = num % MAXN;    if ( flag[k] == false ) return -1;    while ( k != -1 )    {        if ( hash[k].data == num )            return hash[k].id;        k = hash[k].next;    }    return -1;}lint BabyStep_GiantStep ( lint A, lint B, lint C ){    top = MAXN; B %= C;    lint tmp, i, x, y, D;    lint M = (lint)(ceil(sqrt(C+0.0)));    lint K = mod_exp ( A, M, C );    for ( tmp = 1, i = 0; i <= M; tmp = tmp * A % C, i++ )        Insert ( i, tmp );    for ( D = 1, i = 0; i <= M; i++ )    {        ext_gcd ( D, C, x, y );        tmp = ((x * B) % C + C) % C;        if ( (y = Find(tmp)) != -1 )            return i * M + y;        D = D * K % C;    }    return -1;}int main(){    lint P, B, N;    while (scanf("%I64d%I64d%I64d",&P,&B,&N)!=EOF )    {        memset(flag,0,sizeof(flag));        lint ret = BabyStep_GiantStep (B,N,P);        if ( ret == -1 ) printf("no solution\n");        else printf("%I64d\n",ret);    }    return 0;}




下面是HDU 2815 的代码:

#include<cstdio>#include<cmath>#include<cstring>using namespace std;//BabyStep_GiantStep解决离散对数问题#define lint __int64#define MAXN 131071struct HashNode { lint data, id, next; };HashNode hash[MAXN<<1];bool flag[MAXN<<1]; //flag[i] == 0,表示位置i没有放入元素lint top; //用于解决冲突void Insert ( lint a, lint b ){    lint k = b & MAXN;    if ( flag[k] == false )    {        flag[k] = true;        hash[k].next = -1;        hash[k].id = a;        hash[k].data = b;        return;    }    while( hash[k].next != -1 )    {        if( hash[k].data == b ) return;        k = hash[k].next;    }    if ( hash[k].data == b ) return;    hash[k].next = ++top;    hash[top].next = -1;    hash[top].id = a;    hash[top].data = b;}lint Find ( lint b ){    lint k = b & MAXN;    if( flag[k] == false ) return -1;    while ( k != -1 )    {        if( hash[k].data == b ) return hash[k].id;        k = hash[k].next;    }    return -1;}lint gcd ( lint a, lint b ){    return b ? gcd ( b, a % b ) : a;}lint ext_gcd (lint a, lint b, lint& x, lint& y ){    lint t, ret;    if ( b == 0 )    {        x = 1, y = 0;        return a;    }    ret = ext_gcd ( b, a % b, x, y );    t = x, x = y, y = t - a / b * y;    return ret;}lint mod_exp ( lint a, lint b, lint n ){    lint ret = 1;    a = a % n;    while ( b >= 1 )    {        if( b & 1 )            ret = ret * a % n;        a = a * a % n;        b >>= 1;    }    return ret;}lint BabyStep_GiantStep ( lint A, lint B, lint C ){    top = MAXN;  B %= C;    lint tmp = 1, i;    for ( i = 0; i <= 100; tmp = tmp * A % C, i++ )        if ( tmp == B % C ) return i;    lint D = 1, cnt = 0;    while( (tmp = gcd(A,C)) !=1 )    {        if( B % tmp ) return -1;        C /= tmp;        B /= tmp;        D = D * A / tmp % C;        cnt++;    }    lint M = (lint)ceil(sqrt(C+0.0));    for ( tmp = 1, i = 0; i <= M; tmp = tmp * A % C, i++ )        Insert ( i, tmp );    lint x, y, K = mod_exp( A, M, C );    for ( i = 0; i <= M; i++ )    {        ext_gcd ( D, C, x, y ); // D * X = 1 ( mod C )        tmp = ((B * x) % C + C) % C;        if( (y = Find(tmp)) != -1 )            return i * M + y + cnt;        D = D * K % C;    }    return -1;}int main(){    int A,B,C;    while(scanf("%d%d%d",&A,&C,&B)!=EOF)    {        if(B>=C){puts("Orz,I can’t find D!");continue;}        memset(flag,0,sizeof(flag));        int tmp=BabyStep_GiantStep(A,B,C);        if(tmp<0)puts("Orz,I can’t find D!");        else printf("%d\n",tmp);    }    return 0;}


	
				
		
原创粉丝点击