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

     

  • 相关阅读:
    P1541 乌龟棋
    P1725 琪露诺
    P1622 释放囚犯
    P1417 烹调方案
    积木大赛
    换教室
    C#文件和目录的操作
    C#应用程序所有已经打开的窗体的集合
    C#winform自定义滚动条
    C#ADO.NET基础二
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6999389.html
Copyright © 2020-2023  润新知