Discrete Logging hunnu10590 pku2417 fzu 1352 hit 1928 zoj 1898
以下转自: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;
}
/* 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相关推荐
- Discrete Logging POJ - 2417(BSGS)
Discrete Logging POJ - 2417 题意:给P,B,N,求最小的L使得 BL≡N (mod P),其中P是素数. Baby Step Giant Step 1 #include & ...
- POJ 2417 Discrete Logging 离散对数
链接:http://poj.org/problem?id=2417 题意: 思路:求离散对数,Baby Step Giant Step算法基本应用. 下面转载自:AekdyCoin [普通Baby S ...
- POJ2417 Discrete Logging | A,C互质的bsgs算法
题目: 给出A,B,C 求最小的x使得Ax=B (mod C) 题解: bsgs算法的模板题 bsgs 全称:Baby-step giant-step 把这种问题的规模降低到了sqrt(n)级别 首 ...
- BZOJ3239 Discrete Logging
一道裸的BSGS题目(叫baby step, giant step) 从爱酱的blog里学来的,是一个很神的根号算法. 如果我们有hash的工具的话,就是O(sqrt(p))的,这里又用了一个map所 ...
- poj 2417 Discrete Logging
http://poj.org/problem?id=2417 BSGS,直接套之前那题.不过我在multiMod函数里进行了修改,这样这个代码如果输入只是32位有符号数,就不用怕溢出了! 代码如下: ...
- Discrete Logging ZOJ - 1898 (模板题大小步算法)
就是求Ax三B(mod C)当C为素数时 #include<cstdio> #include<cstring> #include<cmath> #include&l ...
- BZOJ 3239 Discrete Logging Baby-Step-Giant-Step
题目大意:给定P,B,N,求最小的L使B^L≡N (mod P) (P是质数) 裸的BSGS... 练练手吧- - #include <cmath> #include <cstdio ...
- POJ前面的题目算法思路【转】
1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 85% 2005-5-7 1002 487-3279 n/a 90% 2005-5- ...
- POJ 超详细分类
POJ 各题算法 1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 ...
最新文章
- JMS分布式应用程序异步消息解决方案EhCache 高速缓存同步问题
- 数据结构与算法09 之图
- apt-get卸载命令
- Jquery中的this是什么类型
- leetcode406. 根据身高重建队列
- arcgis字段计算器利用python按不同两列数据进行编号
- 重磅开源!新型VOLO打破多项记录!
- sql实现从两个表获取字段组成表数据再插入到函数表中
- pstack 安装linux_pstack命令
- 企业如何提升数据质量
- C#.NET通用权限管理系统组件中用少数几行代码实现记录页面状态
- IDC:“互联网+流通”将进一步释放活力
- python刷今日头条阅读量_揭露头条刷阅读量内幕:怎么刷的今日头条阅读量
- 【软件工程习题答案】第八章 维护
- 乡镇医院计算机管理,乡镇卫生院管理系统
- 修复 Fontconfig Error
- php 2个数组并集,php中数组的并集、交集和差集函数介绍_PHP教程
- 仰望流年纯白世界那抹城光(二)
- java中实现多态的机制是什么?
- vue中的@符号的是什么意思
热门文章
- mongo数据库 备份 还原
- python之路-day18-反射
- 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他...
- 第6次cplus实验
- SQL Server 取日期时间部分
- PHP程序员学习路线
- Javascript 你不知道的事
- 在WisOne平台上学习TypeScript
- python修改手机默认语言_修改 CentOS 6.x 上默认Python的方法
- python运算符讲解_python运算符讲解