【文文殿下】ExBSGS

无需逆元版本:

#include<cstdio>
#include<cassert>
#include<cmath>
#include<map>
typedef long long ll;
ll gcd(ll a,ll b) {
	return b?gcd(b,a%b):a;
}
ll qpow(ll a,ll b,ll p) {
	ll ret = 1;
	while(b) {
		if(b&1) {
			ret=ret*a%p;
		}
		a=a*a%p;
		b>>=1;
	}
	return ret;
}
ll exgcd(ll a,ll b,ll &x,ll &y) {
	if(b==0) {
		x=1;y=0;
		return a;
	}
	ll d = exgcd(b,a%b,x,y);
	ll tmp = x;
	x = y;
	y=tmp-a/b*y;
	return d;
}
inline ll bsgs(ll a,ll b,ll p) {
	std::map<ll,ll> M;
	if(p==1) return 0;
	a%=p;b%=p;
	ll d,cnt=0,q=1;
	while((d=gcd(a,p))!=1) {
		if(b==1) return cnt;
		if(b%d) return -1;
		b/=d;
		p/=d;
		++cnt;
		q=a/d*q%p;
	}
	ll lmt = ceil(sqrt(p));
	ll tmp = b%p;
	for(int i = 0;i<lmt;++i,tmp=tmp*a%p) {
		M[tmp]=i;
	}
	tmp = qpow(a,lmt,p);
	for(int i = 1;i<=lmt+1;++i) {
		q=q*tmp%p;
		if(M.count(q)) {
			return i*lmt-M[q]+cnt;
		}
	}
	return -1;
}
int main() {
	ll a,b,p;
	scanf("%lld%lld%lld",&a,&p,&b);
	while(a||b||p) {
		ll ans = bsgs(a,b,p);
		if(ans==-1) puts("No Solution");
		else printf("%lld\n",ans);
		scanf("%lld%lld%lld",&a,&p,&b);
	}
	return 0;
}
posted @ 2019-01-04 17:42  文文殿下  阅读(296)  评论(0编辑  收藏  举报