数论-Baby-Step-Giant-Step算法

大步小步算法(Shank's Baby-Step-Giant-Step Algorithm)

解模方程 ,n为素数(扩展算法处理n不是素数)


似暴力枚举。只要检查x是否=0,1,2,3,..n-1.根据欧拉定理,大于n-1时a^x会循环。

先检查前m项(暂时先记住m = sqrt(n)),检查a^0,a^1,a^2,...a^m-1模n是不是b,每次a^i的值保存在e里

求出a^m的逆a^(-m)(先要学会扩展欧几里得和逆元)。

下面考虑m之后的项:a^m , a^(m+1) ,..a^(2m-1)。

不用逐一检查,因为若a^x  ≡ b(x在这个范围内),那么因为a^x可以表示为ei * a^m,所以存在ei × a^m  ≡ b

利用同余性质,得到ei  ≡ b a^(-m).所以只要检查ei是不是与b a^(-m)同 余即可.

后面的检查,以此类推

我们把e放入STL的map<int, int> x里(打Hash太麻烦)。x[i] = j表示满足e = i这个条件的j,同时j取最小.

LL log_mod(LL a, LL b, LL n) {
	LL m = (LL)sqrt(n+0.5), v, e = 1;
	v = Inv(Qpow(a, m, n), n);
	map<LL, LL> x;
	x.clear();
	x[1] = 0;
	for(LL i=1; i<m; i++) {
		e = mul_mod(e, a, n);
		if(!x.count(e)) x[e] = i;
	}
	for(LL i=0; i<m; i++) { //在m个m里寻找
		if(x.count(b)) return i*m + x[b]; 
		b = mul_mod(b, v, n);
	}
	return -1e9;
}


猜你喜欢

转载自blog.csdn.net/Binary_Heap/article/details/79175079
今日推荐