Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P,
and an integer N, 1 <= N < P, compute the discrete logarithm of N,
base B, modulo P. That is, find an integer L such thatBL == N (mod P)
Input Read several lines of input, each containing P,B,N separated by
a space.Output For each line print the logarithm on a separate line. If there
are several, print the smallest; if there is none, print “no
solution”.
BSGS求离散对数模板题。卡map。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
struct str
{
LL a,t;
bool operator < (const str & s) const
{
return a<s.a||(a==s.a&&t<s.t);
}
}a[100010];
LL p,b,n,m;
void gcd(LL a,LL b,LL &x,LL &y)
{
if (b==0)
{
x=1;
y=0;
return;
}
gcd(b,a%b,y,x);
y-=a/b*x;
}
LL solve()
{
LL i,j,k,x,y,z,inv,tem,l,r,mid;
m=sqrt(p);
a[0]=(str){1,0};
x=1;
for (i=1;i<m;i++)
{
x=x*b%p;
a[i]=(str){x,i};
}
sort(a,a+m);
gcd(x*b%p,p,inv,tem);
inv=(inv%p+p)%p;
for (i=0;i*m<p;i++)
{
l=0;
r=m-1;
while (l<r)
{
mid=(l+r)/2;
if (a[mid].a<n) l=mid+1;
else r=mid;
}
if (a[l].a==n) return a[l].t+i*m;
n=n*inv%p;
}
return -1;
}
int main()
{
LL x;
while (scanf("%lld%lld%lld",&p,&b,&n)==3)
if ((x=solve())>=0) printf("%lld\n",x);
else printf("no solution\n");
}