• POJ 2417 Discrete Logging


    Time Limit: 5000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u

    Description

    Given a prime P, 2 <= P < 2 31, 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) .

    Source

    式子是这个:BL == N (mod P) 求最小的L

    把L分解:L=i*m+j  其中m=sqrt(P)向上取整

    原式化为 B^(i*m)*B^j==N(MOD P)

    再化为B^j===N*B^(-i*m)(MOD P)

    先预处理出B^1  B^2 ... B^(m-1)

    之后求出B^-m,枚举i,如果存在B^(-i*m)存在于HASH表中,说明存在解L=i*m+j

    说了这么多,其实我也不怎么懂2333

    ————————

    隔了一段时间回来,发现代码看不懂了,这和上面写的不一样啊?

    研究了一下,发现确实不一样

    按照上面写的解释,算N*B^(-i*m)很明显需要用到乘法逆元,这就比较麻烦。如何规避这个问题?

    把L分解成L=i*m-j (反正m和j都是待求的,就当m比上面的分解法多了1吧)

      ↑这样原式化为B^(i*m) / B^j == N (MOD P)

            B^(i*m) == N * B^j (MOD P)

      这样就不需要求逆元咯。下面的代码就是这种写法

    ————————

    代码基本靠抄

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int mop=100007;
     8 int hash[mop];
     9 int head[mop],nxt[mop],id[mop],cnt;
    10 void add(int x,int y){//hash
    11     int m=x%mop;
    12     hash[++cnt]=x;nxt[cnt]=head[m];id[cnt]=y;head[m]=cnt;
    13     return;
    14 }
    15 int find(int x){
    16     int m=x%mop;
    17     int i,j;
    18     for(i=head[m];i!=-1;i=nxt[i]){
    19         if(hash[i]==x)return id[i];
    20     }
    21     return -1;
    22 }
    23 int BSGS(int a,int b,int n){//a^x mod n =b
    24     memset(head,-1,sizeof head);
    25     cnt=0;
    26     if(b==1)return 0;
    27     int m=sqrt((double)n),j;
    28     long long x=1,p=1;
    29     for(int i=0;i<m;i++,p=p*a%n)add(p*b%n,i);//预处理b^i 
    30     for(long long i=m; ;i+=m){
    31         x=x*p%n;
    32         if((j=find(x))!=-1)return i-j;
    33         if(i>n)break;
    34     }
    35     return -1;
    36 }
    37 int main(){
    38     int p,b,n;
    39     while(scanf("%d%d%d",&p,&b,&n)!=EOF){
    40         int ans=BSGS(b,n,p);
    41         if(ans==-1)printf("no solution
    ");//无解 
    42         else printf("%d
    ",ans);
    43     }
    44     return 0;
    45 }
  • 相关阅读:
    spring boot多数据源配置(mysql,redis,mongodb)实战
    迷你MVVM框架 avalonjs 学习教程3、绑定属性与扫描机制
    迷你MVVM框架 avalonjs 学习教程2、模块化、ViewModel、作用域
    迷你MVVM框架 avalonjs 学习教程1、引入avalon
    chrome36可以使用自定义元素的回调了
    VML元素的相关资料
    不使用Math.random实现随机数。
    迷你MVVM框架 avalonjs 1.3.4发布
    iscroll源码学习(1)
    对avalon的类名操作进行升级
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5668380.html
Copyright © 2020-2023  润新知