BSGS又称拔山盖世算法
Baby Step Giant Step
又称求离散对数
一般用于给出 a , b , p a, b, p a,b,p求
比较简单,其实就是分块,小块的暴力预处理,然后一块一块跳
借用 psk011102 的图
大概就是这样
先丢个板子题吧:
代码实现很简单:
#include
#define ll long long
using namespace std;
ll p, b, n, mod;
map<ll, ll> mp;
ll qpow(ll x, int y) {
ll ret = 1;
for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
return ret;
}
int BSGS(int p, int b, int n) {
int m = sqrt(p) + 1; ll t = n; mod = p;
for(int i = 0; i <= m; i ++, t = t * b % mod) mp[t] = i;//先把<=m的丢进map里面
ll tt = qpow(b, m); t = tt;//每次跳m个
if(!tt) return n == 0? 1 : -1;//特判0
int f = 0;
for(int i = 1; i <= m + 1; i ++, t = t * tt % mod) {
int j = mp.find(t) == mp.end()? -1 : mp[t];
if(j >= 0) return i * m - j;//如果找到了就返回
}
return -1;
}
int main() {
scanf("%lld%lld%lld", &p, &b, &n);
int l = BSGS(p, b, n);
if(l == -1) printf("no solution");
else printf("%d ", l);
return 0;
}
是不是很简单!!!
要注意这里必须满足 a ⊥ p a \perp p a⊥p
如果不满足呢?
待填坑……