离散对数(Baby Step Giant Step)
2013-02-12 20:04
411 查看
现在我来介绍一种算法叫做Baby Step Giant Step。它是用来解决如下方程最小正整数解的
其中
如果
,那么我们可以先取模,即
,所以在这里我们只讨论
的情况。
普通Baby Step Giant Step的步骤是这样的:
(1)首先确定
的下限是0,上限是
,我们令
(2)把
的值存到一个Hash表里面
(3)把
的值一一枚举出来,每枚举一个就在Hash表里面寻找是否有一个值
满足
,如果有则找到答案,否则继续
(4)最终答案就是
的值对应的原来
的幂
上面是普通Baby Step Giant Step的步骤,比较简单,只适用
为素数的情况。如果
为合数呢?
当
为合数时,我们就需要把Baby Step Giant Step扩展一下。在普通Baby
Step Giant Step中,由于
是素数,那么
,所以
一定有唯一解的。那么,当
为合数时,我们可以这样处理:
对于方程
,我们拿出若干个
出来与
来消去公共因子,使得
为止,那么此时我们就可以直接通过扩展欧几里得来计算结果了。
题目:http://www.spoj.com/problems/MOD/
其中
如果
,那么我们可以先取模,即
,所以在这里我们只讨论
的情况。
普通Baby Step Giant Step的步骤是这样的:
(1)首先确定
的下限是0,上限是
,我们令
(2)把
的值存到一个Hash表里面
(3)把
的值一一枚举出来,每枚举一个就在Hash表里面寻找是否有一个值
满足
,如果有则找到答案,否则继续
(4)最终答案就是
的值对应的原来
的幂
上面是普通Baby Step Giant Step的步骤,比较简单,只适用
为素数的情况。如果
为合数呢?
当
为合数时,我们就需要把Baby Step Giant Step扩展一下。在普通Baby
Step Giant Step中,由于
是素数,那么
,所以
一定有唯一解的。那么,当
为合数时,我们可以这样处理:
对于方程
,我们拿出若干个
出来与
来消去公共因子,使得
为止,那么此时我们就可以直接通过扩展欧几里得来计算结果了。
题目:http://www.spoj.com/problems/MOD/
#include <iostream> #include <string.h> #include <stdio.h> #include <math.h> using namespace std; typedef long long LL; const int MOD = 99991; const int N = 100005; struct Hash { bool f; int id; int val; }; Hash hash ; void Init() { for(int i=0; i<N; i++) { hash[i].f = 0; hash[i].id = -1; hash[i].val = -1; } } void Insert(int id,LL val) { LL t = val % MOD; while(hash[t].f && hash[t].val != val) { t++; t %= MOD; } if(!hash[t].f) { hash[t].f = 1; hash[t].id = id; hash[t].val = val; } } int Find(LL val) { LL t = val % MOD; while(hash[t].f && hash[t].val != val) { t++; t %= MOD; } if(!hash[t].f) return -1; return hash[t].id; } LL gcd(LL a,LL b) { return b ? gcd(b,a%b):a; } void extend_Euclid(LL a,LL b,LL &x,LL &y) { if(b == 0) { x = 1; y = 0; return; } extend_Euclid(b,a%b,x,y); LL tmp = x; x = y; y = tmp - (a / b) * y; } LL Baby_Step(LL A,LL B,LL C) { LL ret = 1; for(int i=0; i<=50; i++) { if(ret == B) return i; ret = ret * A % C; } LL ans = 1; LL tmp,cnt = 0; while((tmp = gcd(A,C)) != 1) { if(B % tmp) return -1; B /= tmp; C /= tmp; ans = ans * (A / tmp) % C; cnt++; } LL M = ceil(sqrt(1.0*C)); LL t = 1; for(int i=0; i<M; i++) { Insert(i,t); t = t * A % C; } for(int i=0; i<M; i++) { LL x,y; extend_Euclid(ans,C,x,y); LL val = x * B % C; val = (val % C + C) % C; LL j = Find(val); if(j != -1) return i * M + j + cnt; ans = ans * t % C; } return -1; } int main() { LL A,B,C; while(cin>>A>>C>>B) { Init(); if(A + B + C == 0) break; A %= C; B %= C; LL ans = Baby_Step(A,B,C); if(ans == -1) { puts("No Solution"); continue; } cout<<ans<<endl; } return 0; }
相关文章推荐
- 【扩展Baby Step Giant Step解决离散对数问题】
- HDU 2815 Mod Tree 离散对数 扩张Baby Step Giant Step算法
- hdu——2815(数论之Baby Step Giant Step解决离散对数问题)
- 【扩展Baby Step Giant Step解决离散对数问题】
- Hdu 2815 Mod Tree + Poj 3243 Clever Y 扩展Baby Step Giant Step 解决离散对数问题
- HDU 2815 Mod Tree【扩展Baby Step Giant Step解决离散对数问题】
- HDU 2815 Mod Tree 离散对数 扩展Baby Step Giant Step算法
- 离散对数学习:baby_step_giant_step与ex_baby_step_giant_step算法
- Baby Step Giant Step算法:求离散对数
- [zz]hdu 2815——Mod Tree【扩展Baby Step Giant Step解决离散对数问题】
- 【扩展Baby Step Giant Step解决离散对数问题】(转自AC神牛。。。。)
- Baby Step Giant Step(好奇怪的名字)及其扩展: 求离散对数
- 【扩展Baby Step Giant Step解决离散对数问题】(转自AC神牛。。。。)
- poj 2417 lightoj 1325 求解离散对数 BABY STEP
- Baby Step Giant Step 及扩展 进一步解释补充 和 poj 3243
- baby step giant step
- poj 2417 Discrete Logging 数论baby_step,giant_step算法
- poj_2417 (baby_step,giant_step算法)
- poj 3243 Clever Y(Baby-Step Giant-Step)
- 邝斌的ACM模板(Baby-Step Giant-Step)