• POJ 2417 Discrete Logging ( Baby step giant step )


    Discrete Logging
    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 3696   Accepted: 1727

    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)

    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".

    Sample Input

    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
    

    Hint

    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 )

    题意要求解一个   k^D = n ( mod p )  的一个最小D

    一开始也不会解 。 

    在网上看了一下,原来是用到一个 Baby step giant step 的算法 。

    先要把 D 分解 ,  D = i * m + j  (  m = ceil( sqrt (p - 1  ) ) )

    原式   :  k^D = n ( mod p ) 

           ->   k^i^m * k^j   = n (mod p )

           ->   k^j = n * ( k ^(-m)^ i ) ( mod p )

    根据题目给的 Hint ( 费马小定理 )可以求出 k^m 的逆元 .

    然后枚举 i  , 查找是否存在 k^j 与 n * ( k ^(-m)^i ) 相等

    所以预处理 k^j (  mod p  ) 排序以后 , 就可以进行二分查找了 (复杂度降为log(m))。 

    加上枚举 , 那么总复杂度就是 m*log(m) .

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long LL ;
    const int N = 100010;
    
    struct B
    {
        LL num , id ;
        bool operator < ( const B &a ) const{
            if( num != a.num ) return num < a.num;
            else return id < a.id ;
        }
    }baby[N];
    
    LL n , k , p ;
    int tot ;
    
    LL quick_mod( LL a , LL b ,LL mod )
    {
        LL res =1 ;
        while( b )
        {
            if( b &1 ) res = res * a % mod ;
            a = a * a % mod ;
            b >>= 1 ;
        }
        return res ;
    }
    int find( LL n )
    {
        int l = 0 , r = tot - 1 ;
        while( l <= r ){
            int m = (l + r) >> 1;
            if( baby[m].num == n){
                return baby[m].id;
            }
            else if( baby[m].num < n )
                l = m + 1;
            else
                r = m - 1 ;
        }
        return -1;
    }
    void run()
    {
        int m = (int)ceil(sqrt((double)(p-1)));
        baby[0].num = 1 , baby[0].id = 0;
        for( int i = 1 ; i < m ; ++i ){
            baby[i].id = i ;
            baby[i].num = baby[i-1].num * k % p ; //   k^j
        }
        sort( baby , baby + m );
        tot = 1 ;
        for( int i = 1 ; i < m ; ++i ){
            if( baby[tot-1].num != baby[i].num ) baby[tot++] = baby[i];
        }
    
        LL bm = quick_mod( k , p - 1 - m , p ) ; //  k^(-m) ;
        LL temp = n ;
    
        for( int j = 0 ; j < m ; ++j ){
            // k^(-m)^j
            int pos = find( temp );
            if( pos != -1 ){
                printf("%d
    " , ( m * j + pos ) );
                return ;
            }
            temp = temp * bm % p ;
        }
        puts("no solution");
    }
    int main()
    {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        while( ~scanf("%lld%lld%lld",&p,&k,&n) ) run();
    }
    only strive for your goal , can you make your dream come true ?
  • 相关阅读:
    PHP学习—Cookie&Session
    IP组播综合实验
    k8s kubeadm部署高可用集群
    python调用zbbix的api实现批量添加域名监控脚本
    Python调用Harbor api删除私有仓库harbor镜像
    Kubernetes故障排查指南-分析容器退出状态码
    blackbox_exporter+grafana+prometheus监控主机存活,端口存活及网站状态
    k8s中使用ceph-csi在ceph中进行数据持久化
    Jenkins+K8S流水线自动化部署Java程序
    生产环境k8s中使用helm部署prometheus+grafana监控k8s集群中相关node和pod
  • 原文地址:https://www.cnblogs.com/hlmark/p/4009212.html
Copyright © 2020-2023  润新知