fogflea
fogflea
发布于 2024-08-23 / 1 阅读
0
0

BSGS算法

离散对数问题

假设有一个同余方程a^x \equiv b \pmod m,其中a,b,m都是给定的整数,am互素。如何求解x的值?

第一个想法可能是暴力枚举,将x0开始枚举到m-1,直到找到一个满足方程的x。时间复杂度是O(m),如果m很大就挂了。

BSGS算法

既然暴力不行,那么我们就要想办法降低时间复杂度。BSGS算法就是一种优化的算法,它的时间复杂度是O(\sqrt{m})。它的思想也很简单。

首先我们令x=A\sqrt{m}-B,其中A,B是两个整数且0\leq A,B\leq \sqrt{m}。那么原方程就变成了a^{A\sqrt{m}-B} \equiv b \pmod m,即a^{A\sqrt{m}} \equiv b\cdot a^B \pmod m

我们可以将方程分解为两个方程:

\begin{cases} c \equiv b\cdot a^B \pmod m\\ a^{A\sqrt{m}} \equiv c \pmod m \end{cases}

对于第一个方程,我们可以从1\sqrt{m}枚举B的值,用一个map存对应B的值。对于第二个方程,依旧从0\sqrt{m}枚举A的值,然后在map中查找是否有相等的b\cdot a^B,获取B的值,最后得到x的值。

//a^x=b(mod p)
LLI BSGS(int a,int b,int p){
	if(a%p==0||b%p==0){//特殊情况
		if(b%p==0&&a%p==0)return 1;
		else return -1;
	}

	map<LLI,LLI> mp;
	LLI cur=1,t=sqrt(p)+1;
	for(LLI B=1;B<=t;++B){
		cur=cur*a%p;
		mp[b*cur%p]=B;
	}
	LLI now=cur;
	for(LLI A=1;A<=t;++A){
		if(mp[now])return A*t-mp[now];
		now=now*cur%p;
	}return -1;
}

评论