foj 1493 基础baby-step-giant-step
2012-11-22 19:41
169 查看
首先讲一下基础的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),进一步转换为(A^m)^i*A^j=B(mod C)
求出(A^i)modC的值并储存到hash中(i from 0 to m)
枚举i(from 0 to m),根据扩展欧几里得得到一个解(由于C是素数,在0-C中只存在一个解),然后在hash表里查找是否存在这个解,如果存在则对应一个j,i*m+j就是问题的最小非负解了。
edit: 发现bug,应该对于hash去一下重,这样才能保证二分的结果最小。 2013/3/22
x=i*m+j (0<=i<m,0<=j<m,m=Ceil(sqrt(C))),问题转变为(A^i)^m*A^j=B(mod C),进一步转换为(A^m)^i*A^j=B(mod C)
求出(A^i)modC的值并储存到hash中(i from 0 to m)
枚举i(from 0 to m),根据扩展欧几里得得到一个解(由于C是素数,在0-C中只存在一个解),然后在hash表里查找是否存在这个解,如果存在则对应一个j,i*m+j就是问题的最小非负解了。
edit: 发现bug,应该对于hash去一下重,这样才能保证二分的结果最小。 2013/3/22
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long llong; struct baby { llong data; int index; }; bool cmp(baby a,baby b) { return a.data<b.data; } baby hash[1<<17]; llong ex_gcd(llong a,llong b,llong& x,llong& y) { if(b==0) { x=1,y=0; return a; } else { llong ans,t; ans=ex_gcd(b,a%b,x,y); t=x; x=y; y=t-a/b*y; return ans; } } int bi_search(llong x,int m) { int l,r,mid; l=0,r=m,mid=(l+r)>>1; while(l<r) { if(hash[mid].data==x) return hash[mid].index; else if(hash[mid].data<x) l=mid+1; else r=mid; mid=(l+r)>>1; } return -1; } llong quickpow(llong a,llong b,llong c) { llong ans=1; while(b) { if(b&1) ans=(ans*a)%c; a=(a*a)%c; b>>=1; } return ans; } llong bsgs(llong a,llong b,llong c) { llong m=llong(sqrt(double(c)))+1; llong i,j,t,AA,gcd,x,y,tmp; t=1,hash[0].index=0,hash[0].data=1; for(i=1;i<m;++i) { t=(t*a)%c; hash[i].data=t; hash[i].index=i; } sort(hash,hash+m,cmp); AA=quickpow(a,m,c); t=1; for(i=0;i<m;++i) { ex_gcd(t,c,x,y); x=(x%c+c)%c; x=(x*b)%c; // for(j=0;j<m;++j) // if(hash[j]==x) // return i*m+j; //超时 j=bi_search(x,m); if(j!=-1) return i*m+j; t=(t*AA)%c; } return -1; } int main() { llong p,g,y,ans; while(scanf("%I64d %I64d %I64d",&p,&g,&y)!=EOF) { ans=bsgs(g,y,p); if(ans==-1) printf("ERROR\n"); else printf("%I64d\n",ans); } return 0; }
相关文章推荐
- 离散对数学习:baby_step_giant_step与ex_baby_step_giant_step算法
- Baby-step giant-step 解高次同余方程a^x=b(mod n) 模版
- poj 2417 && poj3243(Baby-Step Giant-Step)
- POJ - 2417 Discrete Logging(Baby-Step Giant-Step)
- [置顶] hdu2815 扩展Baby step,Giant step入门
- 高次同余方程:poj 3243+poj 2417+hdu 2815 (Baby Step Giant Step 算法)
- 【扩展Baby Step Giant Step解决离散对数问题】(转自AC神牛。。。。)
- poj 2417 Discrete Logging 数论baby_step,giant_step算法
- hdu 2815 Mod Tree 模方程a^x=b(mod n),n为任意正整数+模板题(扩展Baby Step Giant Step)
- 【扩展Baby Step Giant Step解决离散对数问题】
- [bzoj2242][SDOI2011][计算器] (Baby-Step-Giant-Step+快速幂+exgcd)
- bzoj 3283: 运算器 扩展Baby Step Giant Step && 快速阶乘
- POJ 2417 Discrete Logging ( Baby step giant step )
- 高次同余笔记(一):baby-step-giant-step算法
- poj2417(Discrete Logging)-Baby Step Giant Step
- Baby Step Giant Step
- 2417 Discrete Logging 计算最小的x使得a^x=b(mod n) n是素数 Baby_step_Giant_step
- 高次同余方程(Baby-Step Giant-Step)
- 扩展Baby Step Giant Step (解(a^x)%n=b,其中c没有限制)
- 离散对数(Baby Step Giant Step)