Shank的大步小步算法(Shank‘s Baby-Step-Giant-Step Algorithm)
Posted Yan_Bin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shank的大步小步算法(Shank‘s Baby-Step-Giant-Step Algorithm)相关的知识,希望对你有一定的参考价值。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <map> 5 typedef long long LL; 6 int mul_mod(int a,int b,int n){ // a、b都小于n 7 return a * b % n; 8 } 9 int pow_mod(int a,int p,int n){ 10 if(p == 0) return 1; 11 LL ans = pow_mod(a,p / 2,n); 12 ans = ans * ans % n; 13 if(p % 2 == 1) ans = ans * a % n; 14 return ans; 15 } 16 // 求x和y使得ax+by=d并且|x|+|y|最小。其中d=gcd(a,b) 17 void exgcd(int a,int b,int& d,int& x,int& y){ 18 if(!b) d = a,x = 1,y = 0; 19 else{ 20 exgcd(b,a % b,d,y,x); 21 y -= x * (a / b); 22 } 23 } 24 // 计算模n下a的逆,如果gcd(a,n) != 1,则逆不存在,返回-1 25 int inv(int a,int n){ 26 int d,x,y; 27 exgcd(a,n,d,x,y); 28 return d == 1 ? (x + n) % n : -1; 29 } 30 // 求解模方程a^x=b(mod n)。n为素数,无解时返回-1. 31 int log_mod(int a,int b,int n){ 32 int m,v,e = 1,i; 33 m = (int)sqrt(n + 0.5); 34 v = inv(pow_mod(a,m,n),n); // a^m的逆v=a^(-m) 35 std::map<int,int> x; // x[j]表示满足ei(=a^i)=j的最小的i 36 x[1] = 0; 37 for(int i = 1 ; i < m ; i++){ // 计算ei 38 e = mul_mod(e,a,n); 39 if(!x.count(e)) x[e] = i; 40 } 41 // 考虑a^(im)、a^(im+1)、...、a^(im+m-1) 42 for(int i = 0 ; i < m ; i++){ 43 if(x.count(b)) return i * m + x[b]; 44 b = mul_mod(b,v,n); 45 } 46 return -1; 47 } 48 int main(){ 49 printf("%d\n",log_mod(3,4,5)); 50 return 0; 51 }
以上是关于Shank的大步小步算法(Shank‘s Baby-Step-Giant-Step Algorithm)的主要内容,如果未能解决你的问题,请参考以下文章
恶补数论 Baby-Step-Giant-Step 大步小步求离散模对数
bsgs(Baby Steps Giant Steps)算法
题解Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法