BSGS算法

BSGS算法

求关于x的方程a^x = b(mod p),gcd(a,p) = 0下的x;

算法流程:

令x = am -b
y^(am-b) = z(mod p)
y^am = zy^b (mod p)
枚举b = [0,m-1],map记录右边的值,枚举左边的a= [1,m+1]
每次查询右边map中是否有左边的值。O(sqrt(p))

模板:https://www.luogu.com.cn/problem/P3846

ll a,b,p;
ll qpw(ll a,ll b,ll p) {
	a%=p;
	ll ans = 1;
	while(b) {
		if(b & 1)ans = ans*a%p;
		a = a*a%p;
		b>>=1;
	}
	return ans%p;
}

map<ll,ll>mp;

ll BSGS(ll a,ll b,ll p) {  //返回-1表示没找到
	mp.clear();
	if(b == 1) {
		return 0;
	}
	ll ans=-1,m=sqrt(p)+1,xx,s=b;
	for(int i=0; i<m; i++) {
		mp[s] = i;  //右边对应的b
		s = 1ll*s*a%p;
	}
	xx = qpw(a,m,p),s=1;  //左边
	for(int i=1; i<=m+1; i++) {
		s=1ll*s*xx%p;
		if(mp.count(s)) {
			ans = i*m-mp[s];
			break;
		}
	}
	if(ans < 0)return -1;
	else return ans;
}

ex_BSGS : 若gcd(a,b) != 0

算法流程挺烦的,不管了 https://www.luogu.com.cn/problem/P4195

ll ex_BSGS(ll a,ll b,ll p) {
	mp.clear();
	if(b == 1)return 0;
	ll cnt = 0,t=1,s,xx,m;
	for(int d=gcd(a,p); d!=1; d=gcd(a,p)) {
		if(b % d)return -1;
		++cnt,b/=d,p/=d,t=1ll*t*a/d%p;
		if(b == t)return cnt;
	}
	s=b,m=sqrt(p)+1;
	for(int i=0; i<m; i++) {
		mp[s] = i;
		s=1ll*s*a%p;
	}
	xx = qpw(a,m,p),s=t;
	for(int i=1; i<=m; i++) {
		s=1ll*s*xx%p;
		if(mp.count(s))return i*m-mp[s]+cnt;
	}
	return -1;
}
posted @ 2021-05-04 12:07  LaiYiC  阅读(53)  评论(0)    收藏  举报