题目描述
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
B
L
== N (mod P)
输入
Read several lines of input, each containing P,B,N separated by a space,
输出
for each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".
The solution to this problem requires a well known result in number theory that is probably expected of you for Putnam but not ACM competitions. It is Fermat's theorem that states
B
(P-1)
== 1 (mod P)
for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m
B
(-m)
== B
(P-1-m)
(mod P) .
样例输入
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
样例输出
0
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587
题目大意
求关于L的方程B^L≡N(mod P)的最小非负整数解,无解则输出no solution,其中P是质数。
题解
裸的BSGS,参见 bzoj2242
#include <cstdio>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
map<ll , ll> f;
map<ll , ll>::iterator it;
ll pow(ll x , ll y , ll mod)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod;
x = x * x % mod , y >>= 1;
}
return ans;
}
int main()
{
ll p , b , n;
while(scanf("%lld%lld%lld" , &p , &b , &n) != EOF)
{
ll m = (ll)ceil(sqrt(p)) , i , t , temp , flag = 0;
f.clear();
for(t = 1 , i = 0 ; i < m ; t = t * b % p , i ++ )
if(f.find(t) == f.end())
f[t] = i;
for(t = 1 , temp = pow(b , p - m - 1 , p) , i = 0 ; i < m ; t = t * temp % p , i ++ )
{
it = f.find(n * t % p);
if(it != f.end())
{
printf("%lld
" , i * m + it->second) , flag = 1;
break;
}
}
if(!flag) printf("no solution
");
}
return 0;
}