bsgs算法

一、算法简析

BSGS算法(Baby Step Giant Step),可以求解高次同余方程。

条件

正整数 \(a,b,p\),且 \(a\)\(p\) 互质,求满足 \(a^x\equiv b~(mod~p)\) 的最小非负整数 \(x\)

化简

由拓展欧拉定理,得到

\[a^x\equiv a^{x~mod~\varphi(p)+\varphi(p)}~(mod~p) \]

由题意,\(a\)\(p\) 互质,满足欧拉定理,得

\[a^{\varphi(p)}\equiv 1~(mod~p) \]

同乘 \(a^{x~mod~\varphi(p)}\),得

\[a^x\equiv a^{x~mod~\varphi(p)}~(mod~p) \]

因为 \(\varphi(p)<p\),所以仅考虑 \(x\in[0,p]\),能找到答案。直接暴力的效率为 \(O(p)\)

BSGS算法

前期处理

步骤一

\(x=i\times m-j\),其中 \(m=\lceil \sqrt{p} \rceil\)\(i\in[1,m]\)\(j\in[0,m-1]\)
\(x\) 得取值范围为:

  • \(i=1,j=m-1\),则 \(x\) 取最小值。

\[x=1\times m-(m-1)=1 \]

  • \(i=m,j=0\),则 \(x\) 取最大值。

\[x=m\times m - 0=p \]

所以,\(x\in[1,p]\)。因此,对于 \(x=0\) 需要特判。

步骤二

此时,同余方程变为 \(a^{i\times m-j}\equiv b~(mod~p)\),同乘 \(a^j\),得

\[(a^m)^i\equiv b\times a^j~(mod~p) \]

分别计算两边得式子,之后相互匹配即可。

算法详情

  • 遍历 \(j\in[0,m-1]\),计算 \(a^j~(mod~p)\),用哈希表记录 \((a^j, j)\)。如果 \(a^j\) 重复,则用更大的 \(j\) 替代。(因为求 \(x\) 的最小值)
  • 遍历 \(i\in[1,m]\),计算 \((a^m)^i~(mod~p)\),在哈希表中查找是否有对应的 \(a^j\)。若找到这样的 \(j\),则得到答案 \(x=i\times m-j\)

此处有个细节:
我们找到的 \(i\)\(j\) 满足同余方程 \((a^m)^i\equiv b\times a^j~(mod~p)\),但要求的是 \(a^{i\times m-j}\equiv b~(mod~p)\)。这里,两边同除\(a^j\)。对于除法运算,只有 \(a\)\(p\) 互质 时,才成立。(题目中给出了互质关系)

注意点

对于BSGS算法,必须强调 \(a\)\(p\) 互质。算法中,化解(欧拉定理)和得到最终结果(除法运算)都要用到该条件。

二、Code

// 求最小x,使 a^x==b (mod p) 
ll bsgs(ll a, ll b, ll p)
{
	a %= p, b %= p;
	
	if (b == 1)    return 0; // 特判,x=0的情况
	
	ll m = ceil(sqrt(p));
	
	unordered_map<int, int> hash; // 记录<ba^j, j> 
	ll t = b;
	hash[t] = 0; // j=0 
	for (int j = 1; j < m; ++j)
	{
		t = t * a % p;
		hash[t] = j; 
	}
	
	ll mi = 1;
	for (int i = 1; i <= m; ++i) // 计算a^m 
		mi = mi * a % p;
		
	t = 1;
	for (int i = 1; i <= m; ++i) // 计算(a^m)^i 
	{
		t = t * mi % p;
		if (hash.find(t) != hash.end())
			return i * m - hash[t];
	}
	
	return -1; // 不存在x
}

相关题目

P3846 [TJOI2007] 可爱的质数/【模板】BSGS

题目给出的数据范围,\(2\le b,n<p<2^{31}\),暗示 \(b\)\(p\) 互质。


posted @ 2024-05-21 21:32  ltign  阅读(0)  评论(0编辑  收藏  举报