• BSGS算法简述


    BSGS算法主要解决 :求a^x = b ( mod  p ) 的最小满足题意的正整数 x 的问题。

    主要的解决方法是:

      将 x 分成 i * m - j,所以就变成了 a ^( i * m - j ) = b ( mod  p )

      m = ceil ( sqrt ( p ) )

      变形之后即为 ( a ^ m ) ^ i = b *  a ^ j ( mod  p )。

      在(0 -  m )范围内存下b * a ^ j 的值。

      再在 (1 - m )范围枚举,直到( a ^ m ) ^ i 存在与之配对的值,此时 x 可求。 

    具体证明:

      因为 x = i*m-j , 所以x 的最大值不会超过p

      a(k mod p-1) = ak (mod p)  证明这个公式,(需要用到费马小定理)

      k mod p-1 就是 k-m(p-1) ,原式就变成了 ak-m(p-1) ≡ a(mod p)

      再变一步  a/ am(p-1) ≡ a(mod p)

      这时让 am(p-1) ≡ 1 (mod p) 就行了。

      由费马小定理知: 当p为质数且 (a,p1 时 ap-1 ≡ (mod p)

      所以推出 p 为质数 且 (a,p)=1 这个条件, 所以 a(k mod p-1) ≡ (mod p

      所以:如果枚举 x 的话枚举到 p 即可。

      所以使 imj<=p , 即 m=⌈√p⌉ , i,j 最大值也为m。

    感谢 mjtcn

      代码如下:

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<map>
     5 using namespace std;
     6 typedef long long ll;
     7 const int maxn = 1e7 + 7;
     8 ll read()
     9 {
    10     ll a = 0, b = 1;
    11     char c = getchar();
    12     while(c < '0' or c > '9')
    13     {
    14         if(c =='-') b = -1;
    15         c = getchar();
    16     }
    17     while(c >= '0' and c <= '9')
    18     {
    19         a = a * 10 + c - '0';
    20         c = getchar();
    21     }
    22     return a * b;
    23 }
    24 map <ll, int>t;
    25 ll n,b,p;
    26 ll quickpow(ll a, ll b)
    27 {
    28     ll ans = 1;
    29     ll base = a;
    30     while( b != 0)
    31     {
    32         if(b %2 == 1)
    33         ans *= base;
    34         b /= 2;
    35         base*=base;
    36         ans %= p;
    37         base %= p;
    38     }
    39     return ans;
    40 }
    41 int main()
    42 {
    43     p = read(); b = read(); n = read();
    44     //printf("%lld",quickpow(n,b));
    45 /*    for(int i=1; quickpow(b,i) < maxn; i++)
    46     {
    47         t[quickpow(b,i)] = i;
    48     }
    49     for(int i=1; i * p + n < maxn; i++)
    50     {
    51         if(t[i*p + n])
    52         printf("%lld",t[i*p + n]);
    53         break;
    54     }*/
    55     ll m = ceil(sqrt(p));
    56     if(b % p == 0)
    57     {
    58         printf("no solution");
    59         return 0;
    60     }
    61     ll ret , k = 0 ;
    62     ret = n % p;
    63     t[ret] = 0;
    64     for(int i=1; i<=m; i++)
    65     {
    66         ret = (ret * b) % p;
    67         t[ret] = i;
    68     }
    69     ret = quickpow(b,m);
    70     ll now = 1;
    71     for(int i=1; i<=m; i++)
    72     {
    73         now = (now * ret) % p;
    74         if(t[now]) 
    75         {
    76             ll ans = i * m - t[now];
    77             printf("%lld",(ans % p + p) % p);
    78             k = 1;
    79             break;
    80         }
    81     }
    82     if(k == 0)
    83     printf("no solution");
    84     return 0;
    85 }
  • 相关阅读:
    kvm虚拟机添加网卡
    rsync搭建
    hadoop副本数三个变为一个
    nginx日志ip提取参数介绍
    expect使用
    全球语言排行版查询
    mysql忘记密码(跳过权限修改)
    数据备份从阿里云主机(外网主机)拉取到本地服务器
    nginx+keepalived IP飘移(高可用)
    负载均衡配置
  • 原文地址:https://www.cnblogs.com/qmcp/p/9599011.html
Copyright © 2020-2023  润新知