poj2417(Discrete Logging)-Baby Step Giant Step

题目链接:Discrete Logging


题意: ,给你P(P为素数),B,N,让你求满足条件的最小的L,无解输出 no solution.


思路: ,求满足条件的最小x,若p为素数,可用Baby Step Giant Step算法


令m = sqrt(n), 则,先预处理出,存入haxi(hash)表里,

,枚举i,看a^j是否在hash表中,如果找到了,就输出x = i * m + j。




代码:

# include 
# include 
# include 
# include 
# include 
# include 
using namespace std;
typedef long long ll;
const int maxn = (1 << 16);
int b, n, p;

struct Node {
    int val;
    int j;
    bool operator < (const Node& n) const {
        return val < n.val || (val == n.val && j < n.j);
    }
} haxi[maxn];

int exgcd(int a, int b, int& x, int& y) {
    if (!b) {
        x = 1; y = 0; return a;
    }
    int g = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return g;
}

int f_inv(int a) {
    int x, y;
    int g = exgcd(a, p, x, y);
    return g == 1 ? (x + p) % p : -1;
}

int Search(int x, int len) {
    int l = 0, r = len - 1;
    while (l < r) {
        int m = (l + r) / 2;
        if (haxi[m].val >= x) r = m;
        else l = m + 1;
    }
    return haxi[l].val == x ? haxi[l].j : -1;
}

int main(void)
{
    while (~scanf("%d %d %d", &p, &b, &n)) {
        int len = 0;
        int m = sqrt(p + 0.5);
        int t = 1;
        for (int i = 0; i <= m; ++i) {
            haxi[len].val = t;
            haxi[len++].j = i;
            if (i != m) t = (ll)t * b % p;
        }
        sort(haxi, haxi + len);
        int ans = -1;
        int a0 = f_inv(t);
        int a = 1;
        for (int i = 0; i < m; ++i) {
            int val = (ll)n * a % p;
            int id = Search(val, len);
            if (id != -1) {
                ans = i * m + id; break;
            }
            a = (ll)a * a0 % p;
        }
        if (ans != -1) printf("%d\n", ans);
        else printf("no solution\n");
    }

    return 0;
}


你可能感兴趣的:(数学)