其他分享
首页 > 其他分享> > 【模板】BSGS

【模板】BSGS

作者:互联网

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

#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);
}

标签:return,res,ll,float,long,lld,模板,BSGS
来源: https://www.cnblogs.com/bikuhiku/p/BSGS.html