📚【模板】BSGS

给你\(a,b,p\in \mathbb{N}_+\),请解出方程\(a^x\equiv b\pmod p\)的最小解\(x\in\mathbb{N}_+\)

首先设:

\[t = \left\lfloor\sqrt p\right\rfloor \]

\[x = i\times t-j \]

则有:

\[a^{i\times t-j}\equiv b\pmod p \]

于是有:

\[\left(a^t\right)^i\equiv b\times a^j\pmod p \]

现在我们枚举\(j\),建立\(b\times a^j\bmod p\to j\)的映射关系。

然后枚举\(i\),查看映射表中是否有与\(\left(a^t\right)^i\bmod p\)相同的值。

得到\(i,j\),答案即为\(i\times t-j\)

#include <stdio.h>
#include <map>
#define ull unsigned long long
#define ll long long
ll light_multi(ll _a,ll _b,ll _p) {
    _a %= _p, _b %= _p;
    ull _c = (long double)_a*_b/_p;
    ull _x = _a*_b, _y = _c*_p;
    ll _res = (ll)(_x%_p)-(ll)(_y%_p);
    if(_res < 0) _res += _p;
    return _res;
}
ll defended_pow(ll _a,ll _n,ll _p) {
	ll _res = 1;
	while(_n) {
		if(_n&1) _res = light_multi(_res,_a,_p);
		_a = light_multi(_a,_a,_p);
		_n >>= 1;
	}
	return _res;
}
float InvSqrt(float x) {
	float xhalf = 0.5f*x;
	int i = *(int*)&x;
	i = 0x5f375a86-(i>>1);
	x = *(float*)&i;
	x = x*(1.5f-xhalf*x*x);
	x = x*(1.5f-xhalf*x*x);
	x = x*(1.5f-xhalf*x*x);
	return x;
}
std :: map<ll,ll> hash;
ll BSGS(ll a,ll b,ll p) {
	b %= p;
	ll t = (ll)(1.0/InvSqrt(p))+1;
	for(ll i = 0;i < t;++i) 
		hash[b*defended_pow(a,i,p)%p] = i;
	a = defended_pow(a,t,p);//ATP www ;
	if(!a) return b == 0 ? 1 : -1;
	for(ll i = 1;i <= t;++i) {
		ll tmp = defended_pow(a,i,p);
		int j = (hash.find(tmp) == hash.end()) ? -1 : hash[tmp];
		if(j >= 0&&i*t-j >= 0) 
			return i*t-j;
	}
	return -1;
}
ll a, b, p;
signed main() {
	scanf("%lld %lld %lld",&p,&a,&b);
	ll ans = BSGS(a,b,p);
	if(ans == -1)  
		printf("no solution");
	else 
		printf("%lld",ans);
}

\(\text{luogu P3306 [SDOI2013] 随机数生成器}\)


posted @ 2022-07-22 10:53  bikuhiku  阅读(23)  评论(0编辑  收藏  举报