• poj 3243 Clever Y(BabyStep GiantStep)


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

      继续做一下BSGS的题,不过这题有点表述不清,我认为题目应该描述为XY mod Z ≡ K,因为的这题AC算法是不用判断余数是否大于模的。

      本来还想直接贴hdu那题的过去的,结果贴过去以后返回了wa,然后我就开始怀疑自己的BSGS写烂了,在hdu只是轻轻水过而已。于是,我就一个花了一个上午去debug这题,同时认真理解了一下BSGS算法的原理。对于前面一题消因子的方法,http://www.2cto.com/kf/201208/146200.html 这个博客的解释比较容易理解。然后,我就根据思路,仔细的检查了一下代码,同时把某些判断单独处理了。经过长时间的wa,我只好用别人的代码和自己的对拍了,结果发现一个十分可笑的差别,就是别人的代码少了判断余数是否大于等于模这一步,改了以后就AC了。。。。囧!

      我的BSGS是没问题的了,不过这种题见的也不多,所以比较难练啊。。。。- -

    AC代码:

    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     int ret = 0;
     55 
     56     while (b){
     57         if (b & 1) ret += a, ret %= m;
     58         a <<= 1;
     59         a %= m;
     60         b >>= 1;
     61     }
     62 
     63     return 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) && (k || p || n)){
    150         int ans = giantStep(k, p, n);
    151 
    152         if (~ans && ans < p) printf("%d\n", ans);
    153         else puts("No Solution");
    154     }
    155 
    156     return 0;
    157 }

    ——written by Lyon

  • 相关阅读:
    oracle 认证方式
    Oracle
    深入理解Java的接口和抽象类
    mongoDB的学习【小白的福音】
    对于vertical-align的学习
    flex的学习 flexBox的学习
    用伪类添加翘边阴影::before和::after
    icon小图标
    url 中的 ? 和 & 还有 # 的作用
    解决img的1px空白问题
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_3243_Lyon.html
Copyright © 2020-2023  润新知