BZOJ-3239: Discrete Logging

[文章目录]

Description

Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 2 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that BL=N (%p)

BSGS裸题,之前写了个计算器的题一样的。然后,YY了个写hash的过程,将权%一个数,然后挂链,每次寻找的时候扫一遍,感觉还可行。据Po大爷讲,其实可以将i*m+j=x换一种形式,变成aim=b*aj这样就不用求逆元了,当然,p还得是质数。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll b,n;
ll p;
ll mod=1000003,head[1001000],to[101000],nxt[101000],data[101000],z[101000],cnt;
void Hash(ll x,ll val)
{
	ll id=x%mod;
	to[++cnt]=x;
	data[cnt]=val;
	nxt[cnt]=head[id];
	head[id]=cnt;
	z[cnt]=id;
}
ll Find(ll x,ll mx)
{
	ll id=x%mod,re=0;
	for(ll j=head[id];j;j=nxt[j])
		if(to[j]==x&&mx>=data[j]-1) re=max(re,data[j]);
	return re;
}
void clear()
{
	for(ll i=1;i<=cnt;i++)
		head[z[i]]=0;
	cnt=0;
}
ll quick_pow(ll x,ll y)
{
	ll re=1;
	while(y)
	{
		if(y&1) re=re*x%p;
		y>>=1; x=x*x%p;
	}
	return re;
}
int main()
{
	while(~scanf("%lld%lld%lld",&p,&b,&n))
	{
		clear();
		ll m=(int)sqrt(p)+1,now=n;
		for(ll i=0;i<m;i++)
			Hash(now,i+1),now=now*b%p;
		ll inv=quick_pow(b,m); now=1;
		bool flag=1;
		for(ll j=0;j<p;j+=m)
		{
			ll y=Find(now%p,j);
			if(y)
			{
				printf("%d\n",j-y+1);
				flag=0; break;
			}
			now=1ll*now*inv%p;
		}
		if(flag) puts("no solution");
	}
	return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注