BSGS 学习笔记


\(\text{Problem}\)

求解的问题:高次同余方程

\[A^x \equiv B \pmod C,\text{其中}(A,C)=1 \]

\(\text{Algorithm}\)

\(m = \left \lceil \sqrt C \right \rceil\)
考虑 \(x = i \cdot m-j,i \in [1,m],j \in [0,m)\)
然后式子可化为 \(A^{i \cdot m} \equiv B \cdot A^j \pmod C\)
然后枚举 \(j\),考虑哈希存右边式子的值,用哈希表实现
再枚举 \(i\),计算左边式子,然后哈希表中查找,如果找到了,那么答案就是 \(i \cdot m - j\)\(j\) 要在哈希表中记录
时间复杂度为 \(O(\sqrt C)\)

\(\text{Code}\)

#include
#include
#define LL long long
using namespace std;

const int N = 1e6 + 700, mod = 1e6 + 7;
LL p, b, n;

struct hash_table{
	int tot, h[N];
	struct edge{
		LL val;
		int nxt, w;
	}e[N];
	inline hash_table(){tot = 0;}
	inline void insert(LL s, int w)
	{
		LL t = s % mod;
		e[++tot] = edge{s, h[t], w}, h[t] = tot;
	}
	inline int find(LL s)
	{
		LL t = s % mod;
		for(int i = h[t]; i; i = e[i].nxt)
		if (e[i].val == s) return e[i].w;
		return -1;
	}
}H;

int main()
{
	scanf("%lld%lld%lld", &p, &b, &n);
	LL m = ceil(sqrt(p)), BB = 1;
	for(int i = 0; i < m; i++, BB = BB * b % p, n = n * b % p) H.insert(n, i);
	LL B = BB;
	for(int i = 1, j; i <= m; i++, B = B * BB % p)
	if ((j = H.find(B)) != -1)
	{
		printf("%lld\n", m * i - j);
		return 0;
	}
	printf("no solution");
}