• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LyonLys
愿意在角落唱沙哑的歌 再大声也都是给你 请用心听 不要说话 Contact me via E-mail: lyon.lys@gmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅

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

posted @ 2012-09-19 12:10  LyonLys  阅读(197)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3