zoukankan      html  css  js  c++  java
  • 【算法乱讲】BSGS

    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 BL== 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



    显然,这是一道bsgs的裸题
    那么bsgs是什么玩意呢,
    我们先玩一玩式子
    令 m=ceil(sqrt(p))设a^(m*i+j)=b(mod p)

    显然 a^j*a^(m*i)=b(mod p) 
      a^j=b*a^(-m*i) (mod p)

    因此,我们预处理所有可能的a^j丢进哈希表中然后我们枚举i,
    看看有没有可能对应的j
    所以我们的算法时间复杂度为O(n^0.5)
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<iostream>
     4 #include<string>
     5 #include<string.h>
     6 #include<algorithm>
     7 #include<math.h>
     8 #include<queue>
     9 #include<map>
    10 #include<vector>
    11 #include<set>
    12 #define il inline
    13 #define re register
    14 using namespace std;
    15 typedef long long ll;
    16 struct hash_set{
    17     ll v[111111];
    18     int next[111111],g[111111],w[111111],tot;
    19     il void clear(){
    20         memset(g,false,sizeof(g));tot=0;
    21     }
    22     il void insert(ll h,int f){
    23         v[++tot]=h;
    24         w[tot]=f;
    25         next[tot]=g[h%100007];
    26         g[h%100007]=tot;
    27     }
    28     il int find(ll h){
    29         for(re int i=g[h%100007];i;i=next[i])
    30             if(h==v[i]) return w[i];
    31         return -1;
    32     }
    33 } p;
    34 ll A,B,P,m,t,s;
    35 il ll ksm(re ll base,re ll pow){
    36     if(pow<0){
    37         cout<<"-1";exit(0);
    38     }
    39     ll ans=1;
    40     for(;pow;pow>>=1){
    41         if(pow&1) ans=ans*base%P;
    42         base=base*base%P; 
    43     }
    44     return ans;
    45 }
    46 il ll rev(re ll a){
    47     return ksm(a,P-2);
    48 }
    49 il void init(){
    50     p.clear();
    51     m=ceil(sqrt(P));t=1;
    52     for(int i=0;i<m;i++){
    53         if(p.find(t)<0) p.insert(t,i);
    54         t=t*A%P;
    55     }
    56     //cout<<endl;
    57     for(int i=0,l;i<=P/m;i++){
    58         t=rev(ksm(A,m*i));
    59     //    cout<<t<<" "<<m*i<<" ";
    60         s=t*B%P;
    61     //    cout<<s<<endl;
    62         l=p.find(s);
    63         if(l>=0){
    64             printf("%lld
    ",m*i+l);
    65             return;
    66         }
    67     }
    68     printf("no solution
    ");
    69 }
    70 int main(){
    71     while(scanf("%lld%lld%lld",&P,&A,&B)!=EOF){
    72         init();
    73     }
    74     return 0;
    75 }
    
    
  • 相关阅读:
    C++ 打印 vector
    使用 winsock 实现简单的 Client 和 Server
    Windows 10 Clion 配置 Opencv 4.0.1
    解决编译的时候头文件找不到的问题
    linux内核打印内存函数print_hex_dump使用方法
    ubuntu180
    驱动编译相关
    Real-Time Rendering 4th Chapter 1 Introduction 简介 转载
    do_gettimeofday使用方法
    6、设备树实践操作
  • 原文地址:https://www.cnblogs.com/ExiledPoet/p/5836006.html
Copyright © 2011-2022 走看看