zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    赫尔维茨公式
    从解析几何的角度分析二次型
    Struts 1 Struts 2
    记一次服务器被入侵的调查取证
    契约式设计 契约式编程 Design by contract
    lsblk df
    Linux Find Out Last System Reboot Time and Date Command 登录安全 开关机 记录 帐号审计 历史记录命令条数
    Infrastructure for container projects.
    更新文档 版本控制 多版本并发控制
    Building Microservices: Using an API Gateway
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_2417_Lyon.html
Copyright © 2011-2022 走看看