zoukankan      html  css  js  c++  java
  • poj 2417 Discrete Logging ---高次同余第一种类型。babystep_gaint_step

    Discrete Logging
    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 2831   Accepted: 1391

    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
    
     
    经典的高次同余,C是质数,那么A,C互质。A^x = B(mod C)
      1 /*
      2 
      3 模板题baby_step.
      4 Hash + 扩展欧几里得 +拆分思想
      5 
      6 题意:
      7 求A^x = B( mod C )的最小x,其中C是一个质数。
      8 思路:
      9 用普通的babystep_gaint_step即可,具体的做法是这样的,我们把x写成下面这样
     10 的形式:x = i * m + j , 这样上式就可以变成:A^m^i * A^j = B( mod C ),其中m=
     11 ceil( sqrt(C) ),0<=i<m , 0<=j <m,接下去我们先求出所有的A^j % C的值,并且把
     12 它们存到一个hash表中去,接下去就是先处理出A^m%C的值,记作D,现在上式就
     13 变成了这样:D^i * A^j = B( mod C ), 现在我们从0-m-1枚举i,这样D^i的值就
     14 已经知道了,记为DD,下面我们先令A^j 为x,式子就变成了:DD*x = B( mod C )
     15 这个式子是可以通过普通的扩展欧几里得算法求出x的解的(这个方程的x在0-C
     16 内一定会只有一个唯一的解,因为gcd(DD, C) == 1, C是质数),然后在建好的hash
     17 表中查找这个x是否存在,若是存在,则输出此时的i*m+j,就是答案。下面说明一下,
     18 为什么x只需要考虑0-C的解就可以了,如果解存在,则上面已经说明,一定会在0-
     19 C范围内存在一个解,因为是找最小的解,因此这时候的解就是答案;如果不存在
     20 解,我们下面将要说明只需要考虑0-C范围内无解,方程就不会有解了。证明的过程
     21 大致是这样的,首先如果方程在0 -- C内都没有解, 考虑A^x%C的值,由鸽笼原理可
     22 知,余数中势必要出现循环节,而且循环节的长度是C的欧拉函数值,也就是说接下
     23 去的x的余数将进入一个循环,从而将不会得出解了。
     24 
     25 */
     26 
     27 #include<iostream>
     28 #include<cstdio>
     29 #include<cstdlib>
     30 #include<cstring>
     31 #include<math.h>
     32 using namespace std;
     33 
     34 typedef __int64 LL;
     35 const int MAX=499991;
     36 LL A,B,C;
     37 bool Hash[MAX];
     38 LL idx[MAX];
     39 LL val[MAX];
     40 
     41 void Ex_gcd(LL a,LL b,LL &x,LL &y)
     42 {
     43     if(b==0)
     44     {
     45         x=1;
     46         y=0;
     47         return ;
     48     }
     49     Ex_gcd(b,a%b,x,y);
     50     LL hxl=x-(a/b)*y;
     51     x=y;
     52     y=hxl;
     53 }
     54 
     55 LL Euler(LL n)
     56 {
     57     LL i,temp=n;
     58     for(i=2;i*i<=n;i++)
     59     {
     60         if(n%i==0)
     61         {
     62             while(n%i==0)
     63             n=n/i;
     64             temp=temp/i*(i-1);
     65         }
     66     }
     67     if(n!=1)
     68     temp=temp/n*(n-1);
     69     return temp;
     70 }
     71 
     72 void Insert(LL id,LL num)
     73 {
     74     LL k=num%MAX;
     75     while(Hash[k] && val[k]!=num)
     76     {
     77         k++;
     78         if(k==MAX) k=k-MAX;
     79     }
     80     if(!Hash[k])
     81     {
     82         Hash[k]=1;
     83         idx[k]=id;
     84         val[k]=num;
     85     }
     86 }// Hash make
     87 
     88 LL found(LL num)
     89 {
     90     LL k=num%MAX;
     91     while(Hash[k] && val[k]!=num)
     92     {
     93         k++;
     94         if(k==MAX) k=k-MAX;
     95     }
     96     if(!Hash[k])
     97     {
     98         return -1;
     99     }
    100     return idx[k];
    101 }// Hash find
    102 
    103 LL baby_step(LL a,LL b,LL c)
    104 {
    105     LL M=ceil(sqrt(Euler(c)*1.0));
    106     memset(Hash,false,sizeof(Hash));
    107     memset(idx,-1,sizeof(idx));
    108     memset(val,-1,sizeof(val));
    109     LL D=1;
    110     for(LL i=0;i<M;i++)
    111     {
    112         Insert(i,D);
    113         D=D*a%c;
    114     }//maek D;
    115 
    116     LL res=1;
    117     LL x,y;
    118     for(LL i=0;i<M;i++)
    119     {
    120         Ex_gcd(res,c,x,y);
    121         LL tmp=x*b%c;
    122         tmp=(tmp%c +c)%c;
    123         LL k=found(tmp);
    124         if(k!=-1)
    125         {
    126             return LL(i)*M+k;
    127         }
    128         res=res*D%c;
    129     }
    130     return -1;
    131 }
    132 
    133 int main()
    134 {
    135     while(scanf("%I64d%I64d%I64d",&C,&A,&B)>0)
    136     {
    137         LL res=baby_step(A,B,C);
    138         if(res==-1)
    139         {
    140             printf("no solution
    ");
    141         }
    142         else printf("%I64d
    ",res);
    143     }
    144     return 0;
    145 }
  • 相关阅读:
    CodeForces 797D Broken BST
    CodeForces 797C Minimal string
    CodeForces 797B Odd sum
    CodeForces 797A k-Factorization
    CodeForces 772B Volatile Kite
    OpenCV学习笔记二十:opencv_ts模块
    OpenCV学习笔记十九:opencv_gpu*模块
    OpenCV学习笔记十八:opencv_flann模块
    OpenCV学习笔记十七:opencv_bioinspired模块
    OpenCV学习笔记十六:opencv_calib3d模块
  • 原文地址:https://www.cnblogs.com/tom987690183/p/3284123.html
Copyright © 2011-2022 走看看