BSGS学习笔记

BSGS算法

BSGS算法使用来求解\(x\)的方程
\[ x ^ y \equiv z\pmod p \]
其中\(gcd(x, p) = 1\), 我们将\(y\)写做一个\(am - b\)的形式, 其中\(a \in (1, m + 1]\), \(b \in [0, m)\)

那么这样, 原式就变成了
\[ \begin{aligned} x^{am - b} &\equiv z \pmod p\\ x^{am} &\equiv z * x ^ b \pmod p \end{aligned} \]
我们枚举每一个\(b\), 将\(z * x ^ b\)存进\(hash\)或者\(map\)之类的东西

之后对于左边枚举每一个\(a\), 如果\(x ^ {am} \% p\)\(hash\)或者\(map\)中, 答案就为\(a * m - mp[x ^ {am} \% p]\)

复杂度为\(O(max(m, p / m))\), 易证得\(m\)\(\sqrt{p}\)的时候最优

代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <map>
#define itn int
#define reaD read
using namespace std;

int p, x, y, s, m;
map<int, int> mp; 

inline int read()
{
    int x = 0, w = 1; char c = getchar();
    while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * w;
}

int fpow(int x, int k)
{
    int res = 1;
    while(k)
    {
        if(k & 1) res = 1ll * res * x % p;
        x = 1ll * x * x % p;
        k >>= 1; 
    }
    return res; 
}

int main()
{
    p = reaD(); x = read(); y = read(); m = sqrt(p) + 1; s = y; 
    for(int i = 0; i < m; i++) mp[s] = i, s = 1ll * s * x % p; 
    s = 1; int t = fpow(x, m); 
    for(int i = 1; i <= m + 1; i++)
    {
        s = 1ll * s * t % p; 
        if(mp.count(s))
        {
            printf("%d\n", i * m - mp[s]);
            return 0; 
        }
    }
    puts("no solution"); 
    return 0;
}

ExBSGS算法

好像所有有\(Ex\)的算法似乎都是在不互质的情况下诶

这里, \(ExBSGS\)是用来处理\(gcd(x, p) != 1\)的情况的, 我们可以有这样一个式子, 设\(gcd(x, p) = d\)
\[ <Empty \space Math \space Block> \]

猜你喜欢

转载自www.cnblogs.com/ztlztl/p/11024724.html
今日推荐