题目链接: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 <iostream>
# include <algorithm>
# include <cstdio>
# include <cstring>
# include <cmath>
# include <map>
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;
}