Time Limit: 5000MS Memory Limit: 65536K
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 that B^L == N (mod P)
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”.
5 2 1 5 2 2 5 2 3 5 2 4 5 3 1 5 3 2 5 3 3 5 3 4 5 4 1 5 4 2 5 4 3 5 4 4 12345701 2 1111111 1111111121 65537 1111111111
Sample Output
0 1 3 2 0 3 1 2 0 no solution no solution 1 9584351 462803587
Solution
一道BSGS模板题啦,留作纪念……
Code
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const ll mod=
76543;
ll P,B,N,ans,top,hs[mod],id[mod],Last[mod],Next[mod];
void Insert(ll x,ll y)
{
ll z=x%mod;
hs[++top]=x,id[top]=y,Next[top]=Last[z],Last[z]=top;
}
ll Find(ll x)
{
ll z=x%mod;
for(ll i=Last[z];i;i=Next[i])
if(hs[i]==x)
return id[i];
return -
1;
}
ll BSGS(ll a,ll b,ll c)
{
if(b==
1)
return 0;
ll m=
ceil(
sqrt(c)),j=
1,t=
1,k;
for(ll i=
0;i<m;i++,j=j*a%c) Insert(j*b%c,i);
for(ll i=m;i<=c;i+=m)
if(~(k=Find(t=t*j%c)))
return i-k;
return -
1;
}
int main()
{
while(~
scanf(
"%lld%lld%lld",&P,&B,&N))
{
top=
0,
memset(Last,
0,
sizeof(Last));
ans=BSGS(B,N,P);
if(~ans)
printf(
"%lld\n",ans);
else puts(
"no solution");
}
return 0;
}