• poj 2417 Discrete Logging


    http://poj.org/problem?id=2417

      BSGS,直接套之前那题。不过我在multiMod函数里进行了修改,这样这个代码如果输入只是32位有符号数,就不用怕溢出了!

    代码如下:

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <map>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 typedef __int64 ll;
      9 
     10 //map<int, int> EP;
     11 
     12 const int maxn = 500007;
     13 int hash[maxn], EP[maxn];
     14 
     15 bool insert(int x, int k){
     16     int p = (x << 6) % maxn;
     17 
     18     if (p < 0) p += maxn;
     19     while (hash[p] != x && ~EP[p]) p = (p + 1) % maxn;
     20 
     21     if (hash[p] == x && ~EP[p]) return false;
     22 
     23     hash[p] = x;
     24     EP[p] = k;
     25 
     26     return true;
     27 }
     28 
     29 int find(int x){
     30     int p = (x << 6) % maxn;
     31 
     32     if (p < 0) p += maxn;
     33     while (hash[p] != x && ~EP[p]) p = (p + 1) % maxn;
     34 
     35     return EP[p];
     36 }
     37 
     38 int gcd(int a, int b){
     39     return b ? gcd(b, a % b) : a;
     40 }
     41 
     42 void exgcd(int a, int b, ll &x, ll &y){
     43     if (b){
     44         exgcd(b, a % b, y, x);
     45         y -= (a / b) * x;
     46     }
     47     else{
     48         x = 1;
     49         y = 0;
     50     }
     51 }
     52 
     53 int multiMod(int a, int b, int m){
     54     ll ret = 0, tmp;
     55 
     56     while (b){
     57         if (b & 1) ret += a, ret %= m;
     58         tmp = (ll)a << 1;
     59         a = tmp % m;
     60         b >>= 1;
     61     }
     62 
     63     return (int)ret;
     64 }
     65 
     66 int powMod(int p, int n, int m){
     67     int ret = 1;
     68 
     69     while (n){
     70         if (n & 1) ret = multiMod(ret, p, m);
     71         p = multiMod(p, p, m);
     72         n >>= 1;
     73     }
     74 
     75     return ret;
     76 }
     77 
     78 int babyStep(int &p, int &m, int &rest, int &base, int &mark){
     79     // return 0: cnt is answer
     80     // return -1: no solution
     81     // return else: base counts before steps, and mark is base-pow and return size
     82     int t, cur = 1 % m;
     83 
     84     mark = 1 % m;
     85     base = 0;
     86 //    EP.clear();
     87     memset(EP, -1, sizeof(EP));
     88     while ((t = gcd(p, m)) != 1){
     89         if (rest % t) return -1;
     90         base++;
     91         m /= t;
     92         rest /= t;
     93         mark = multiMod(mark, p / t, m);
     94     }
     95 
     96     int r = (int) ceil(sqrt((double) m));
     97 
     98     cur = 1 % m;
     99     for (int i = 0; i <= r; i++){
    100 //        if (EP.count(cur)) break;
    101 //        EP[cur] = i;
    102         if (!insert(cur, i)) break;
    103         cur = multiMod(cur, p, m);
    104     }
    105 
    106     return r;
    107 }
    108 
    109 int giantStep(int p, int m, int rest){
    110     //if (rest >= m) return -1;
    111 
    112     rest %= m;
    113     for (int i = 0, cur = 1 % m; i <= 50; i++){ // before baby-step try whether there is a simple solution
    114         if (cur == rest){
    115             return i;
    116         }
    117         cur = multiMod(cur, p, m);
    118     }
    119 
    120     int tmp, cnt;
    121     int r = babyStep(p, m, rest, cnt, tmp);
    122 
    123     if (r == -1) return -1;
    124 
    125     int ep = powMod(p, r, m); // cycle-length
    126 
    127     if (!r)    return cnt;
    128     for (int i = 0; i <= r; i++){
    129         ll x, y;
    130 
    131         exgcd(tmp, m, x, y);
    132         x = multiMod(x, rest, m);
    133         if (x < 0) x += m;
    134 //        if (EP.count((int)x)){
    135 //            return EP[(int)x] + i * r + cnt;
    136 //        }
    137         int f = find((int)x);
    138 
    139         if (~f) return f + i * r + cnt;
    140         tmp = multiMod(tmp, ep, m);
    141     }
    142 
    143     return -1;
    144 }
    145 
    146 int main(){
    147     int k, p, n;
    148 
    149     while (~scanf("%d%d%d", &k, &p, &n)){
    150         int ans = giantStep(p, k, n);
    151 
    152         if (~ans) printf("%d\n", ans);
    153         else puts("no solution");
    154     }
    155 
    156     return 0;
    157 }

    ——written by Lyon

  • 相关阅读:
    HDU-统计难题
    POJ-A Simple Problem with Integers
    HDU-I Hate It
    个人站立会议06
    个人站立会议05
    个人站立会议04
    易校小程序典型用户需求分析
    个人站立会议03
    个人第二次晚间站立总结会议
    个人站立会议02
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_2417_Lyon.html
Copyright © 2020-2023  润新知