【bzoj3239】Discrete Logging BSGS

题目描述

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\n" , i * m + it->second) , flag = 1;
                break;
            }
        }
        if(!flag) printf("no solution\n");
    }
    return 0;
}

 

 

posted @ 2017-06-13 09:18  GXZlegend  阅读(257)  评论(0编辑  收藏  举报