以下转自:http://hi.baidu.com/aekdycoin/blog/item/b317ca18bb24334942a9ad55.html

【普通Baby Step Giant Step】

【问题模型】
求解
A^x = B (mod C) 中 0 <= x < C 的解,C 为素数

【思路】
我们可以做一个等价
x = i * m + j  ( 0 <= i < m, 0 <=j < m) m = Ceil ( sqrt( C) )
而这么分解的目的无非是为了转化为:
(A^i)^m * A^j = B ( mod C)

之后做少许暴力的工作就可以解决问题:
(1) for i = 0 -> m, 插入Hash (i, A^i mod C)
(2) 枚举 i ,对于每一个枚举到的i,令  AA = (A^m)^i mod C
我们有
AA * A^j = B (mod C)
显然AA,B,C均已知,而由于C为素数,那么(AA,C)无条件为1
于是对于这个模方程解的个数唯一(可以利用扩展欧几里得或 欧拉定理来求解)
那么对于得到的唯一解X,在Hash表中寻找,如果找到,则返回 i * m + j
注意:由于i从小到大的枚举,而Hash表中存在的j必然是对于某个剩余系内的元素X 是最小的(就是指标)
所以显然此时就可以得到最小解

如果需要得到 x > 0的解,那么只需要在上面的步骤中判断 当 i * m + j > 0 的时候才返回

到目前为止,以上的算法都不存在争议,大家实现的代码均相差不大。可见当C为素数的时候,此类离散对数的问题可以变得十分容易实现。

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define nmax 46341
#define LL long long
typedef struct Num {int nnum;int ii;
} Num;
Num num[nmax];
int x, y;
int cmp(const void *a, const void *b) {Num *n = (Num *) a;Num *m = (Num *) b;if (n->nnum > m->nnum) {return 1;}return -1;
}
int extend_gcd(int a, int b) {if (b == 0) {x = 1, y = 0;return a;}int d = extend_gcd(b, a % b);int tx = x;x = y;y = tx - a / b * y;return d;
}
int find_num(int x, int n) {int mid, left, right;left = 0, right = n + 1;while (left <= right) {mid = (left + right) >> 1;if (num[mid].nnum == x) {return num[mid].ii;} else if (num[mid].nnum > x) {right = mid - 1;} else {left = mid + 1;}}return -1;
}
int main() {
#ifndef ONLINE_JUDGEfreopen("t.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifLL ptemp, te;int i, j, pte, p, b, n, bb, temp;while (scanf("%d %d %d", &p, &b, &n) != EOF) {pte = (int) ((sqrt(p * 1.0) + 0.5));for (i = 0, ptemp = 1; i <= pte; i++) {num[i].nnum = (int) (ptemp);num[i].ii = i;ptemp = ptemp * b % p;}bb = num[pte].nnum;qsort(num, pte + 1, sizeof(num[0]), cmp);for (i = 0, ptemp = 1; i <= pte; i++) {temp = (int) (ptemp);extend_gcd(temp, p);te = (int) (x);te = te * n;te = te % p + p;x = (int) (te % p);j = find_num(x, pte);if (j != -1) {printf("%d\n", pte * i + j);break;}ptemp = ptemp * bb % p;}if (i > pte) {printf("ERROR\n");}}return 0;
}

hunnu 10590 fzu 1352 pku 2417 hit 1928 zoj 1898
 
/* a^x=b (mod c) c is prime*/#include<stdio.h>#include<math.h>#include<string.h>#include<stdlib.h>#define LL long long#define nmax 46345typedef struct num {int ii, value;} num;num Num[nmax];int x, y;int cmp(const void *a, const void *b) {    num n = *(num *) a;    num m = *(num *) b;return n.value - m.value;}void extend_gcd(int a, int b) {int xx;if (b == 0) {        x = 1, y = 0;return;    }    extend_gcd(b, a % b);    xx = x;    x = y, y = xx - a / b * y;}int bfindNum(int key, int n) {int left, right, mid;    left = 0, right = n;while (left <= right) {        mid = (left + right) >> 1;if (Num[mid].value == key) {return Num[mid].ii;        } else if (Num[mid].value > key) {            right = mid - 1;        } else {            left = mid + 1;        }    }return -1;}void solve(int c, int a, int b) {int i, j, te, aa;    LL temp, xx;    te = (int) (sqrt(c * 1.0) + 0.5);for (i = 0, temp = 1 % c; i <= te; i++) {        Num[i].ii = i;        Num[i].value = (int) (temp);        temp = temp * a % c;    }    aa = Num[te].value;    qsort(Num, te + 1, sizeof(Num[0]), cmp);for (i = 0, temp = 1; i <= te; i++) {        extend_gcd((int) (temp), c);        xx = (LL) x;        xx = xx * b;        xx = xx % c + c;        x = (int) (xx % c);        j = bfindNum(x, te + 1);if (j != -1) {            printf("%d\n", i * te + j);return;        }        temp = temp * aa % c;    }    puts("no solution");}int main() {#ifndef ONLINE_JUDGE    freopen("data.in", "r", stdin);#endifint p, b, n;while (~scanf("%d %d %d", &p, &b, &n)) {        solve(p, b, n);    }return 0;}

转载于:https://www.cnblogs.com/xiaoxian1369/archive/2011/08/04/2127447.html

Discrete Logging hunnu10590 pku2417 fzu 1352 hit 1928 zoj 1898相关推荐

  1. Discrete Logging POJ - 2417(BSGS)

    Discrete Logging POJ - 2417 题意:给P,B,N,求最小的L使得 BL≡N (mod P),其中P是素数. Baby Step Giant Step 1 #include & ...

  2. POJ 2417 Discrete Logging 离散对数

    链接:http://poj.org/problem?id=2417 题意: 思路:求离散对数,Baby Step Giant Step算法基本应用. 下面转载自:AekdyCoin [普通Baby S ...

  3. POJ2417 Discrete Logging | A,C互质的bsgs算法

    题目: 给出A,B,C 求最小的x使得Ax=B  (mod C) 题解: bsgs算法的模板题 bsgs 全称:Baby-step giant-step 把这种问题的规模降低到了sqrt(n)级别 首 ...

  4. BZOJ3239 Discrete Logging

    一道裸的BSGS题目(叫baby step, giant step) 从爱酱的blog里学来的,是一个很神的根号算法. 如果我们有hash的工具的话,就是O(sqrt(p))的,这里又用了一个map所 ...

  5. poj 2417 Discrete Logging

    http://poj.org/problem?id=2417 BSGS,直接套之前那题.不过我在multiMod函数里进行了修改,这样这个代码如果输入只是32位有符号数,就不用怕溢出了! 代码如下: ...

  6. Discrete Logging ZOJ - 1898 (模板题大小步算法)

    就是求Ax三B(mod C)当C为素数时 #include<cstdio> #include<cstring> #include<cmath> #include&l ...

  7. BZOJ 3239 Discrete Logging Baby-Step-Giant-Step

    题目大意:给定P,B,N,求最小的L使B^L≡N (mod P) (P是质数) 裸的BSGS... 练练手吧- - #include <cmath> #include <cstdio ...

  8. POJ前面的题目算法思路【转】

    1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 85% 2005-5-7 1002 487-3279 n/a 90% 2005-5- ...

  9. POJ 超详细分类

    POJ 各题算法 1000    A+B Problem            送分题     49%    2005-5-7 1001    Exponentiation         高精度   ...

最新文章

  1. JMS分布式应用程序异步消息解决方案EhCache 高速缓存同步问题
  2. 数据结构与算法09 之图
  3. apt-get卸载命令
  4. Jquery中的this是什么类型
  5. leetcode406. 根据身高重建队列
  6. arcgis字段计算器利用python按不同两列数据进行编号
  7. 重磅开源!新型VOLO打破多项记录!
  8. sql实现从两个表获取字段组成表数据再插入到函数表中
  9. pstack 安装linux_pstack命令
  10. 企业如何提升数据质量
  11. C#.NET通用权限管理系统组件中用少数几行代码实现记录页面状态
  12. IDC:“互联网+流通”将进一步释放活力
  13. python刷今日头条阅读量_揭露头条刷阅读量内幕:怎么刷的今日头条阅读量
  14. 【软件工程习题答案】第八章 维护
  15. 乡镇医院计算机管理,乡镇卫生院管理系统
  16. 修复 Fontconfig Error
  17. php 2个数组并集,php中数组的并集、交集和差集函数介绍_PHP教程
  18. 仰望流年纯白世界那抹城光(二)
  19. java中实现多态的机制是什么?
  20. vue中的@符号的是什么意思

热门文章

  1. mongo数据库 备份 还原
  2. python之路-day18-反射
  3. 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他...
  4. 第6次cplus实验
  5. SQL Server 取日期时间部分
  6. PHP程序员学习路线
  7. Javascript 你不知道的事
  8. 在WisOne平台上学习TypeScript
  9. python修改手机默认语言_修改 CentOS 6.x 上默认Python的方法
  10. python运算符讲解_python运算符讲解