poj Discrete Logging (Baby-step-Giant - step)

                                    Discrete Logging


题目:

     Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that 

    BL == N (mod P)

算法:

     模板题。但是,要Hash维护。不然,会超时。第一次就没有,Tel了。囧。。。。。


模板:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

typedef long long LL;

namespace HASH{
  const int MAXN = 65535;

  struct hash{
     int a,b,next;
  }Hash[MAXN << 1];
  int flg[MAXN + 66];
  int top,idx;
  void init(){  //初始化
     top = MAXN; ++idx; //!!!!!!!!!
  }
  void ins(int a,int b){ //Hash插入
      int k = b&MAXN;
      if(flg[k] != idx){
          flg[k] = idx;
          Hash[k].next = -1;
          Hash[k].a = a;
          Hash[k].b = b;
          return;
      }
      while(Hash[k].next != -1){
          if(Hash[k].b == b) return;
          k = Hash[k].next;
      }
      Hash[k].next = ++top;
      Hash[top].next = -1;
      Hash[top].a = a;
      Hash[top].b = b;
  }
  int find(int b){     //hash茶查找
      int k = b & MAXN;
      if(flg[k] != idx) return -1;
      while(k != -1){
          if(Hash[k].b == b) return Hash[k].a;
          k = Hash[k].next;
      }
      return -1;
  }
}

namespace MATH{
    typedef long long LL;

    int gcd(int a,int b){ return b?gcd(b,a%b):a;}
    int extgcd(int a,int b,int& x,int& y){
        int ret,t;
        if(!b){ x = 1; y = 0; return a; }
        ret = extgcd(b,a%b,x,y);
        t = x,x = y,y = t - (LL)a/b*y;
        return ret;
    }
    int pow_mod(LL a,int b,int p){
        LL res = 1%p;
        a %= p;
        while(b > 0){
            if(b & 1) res = res * a % p;
            a = a * a % p;
            b >>= 1;
        }
        return res;
    }
    int Inval(int a,int b,int n){
        int e,x,y;
        extgcd(a,n,x,y);
        e = (LL)x*b%n;
        return e < 0 ? e+n : e;
    }
}

//A^x = B(mod C)
int BabyStep(int A,int B,int C){
    HASH::init();
    LL buf = 1 % C,D = buf,K;
    int i,d = 0,tmp;
    for(i=0;i<=100;buf=buf*A%C,++i) if(buf==B) return i;
    while((tmp = MATH::gcd(A,C)) != 1){ //消除因子
        if(B%tmp) return -1;
        ++d;
        C /= tmp;
        B /= tmp;
        D = D*A/tmp%C;
    }
    int M = (int)ceil(sqrt(C+0.5));
    for(buf=1%C,i=0;i<=M;buf=buf*A%C,++i) HASH::ins(i,buf);
    for(i= 0,K=MATH::pow_mod((LL)A,M,C);i<=M;D=D*K%C,++i){
        tmp = MATH::Inval((int)D,B,C); int w;
        if(tmp>=0&&(w=HASH::find(tmp)) != -1) return i*M+w+d;
    }
    return -1;
}

int  main(){
    int A,B,C;
    while(~scanf("%d%d%d",&C,&A,&B)){
        B %= C;
        int res = BabyStep(A,B,C);
        if(res < 0){
            puts("no solution");
        } else {
            printf("%d\n",res);
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值