bsgs(大步小步演算法)和exbsgs(擴充套件大步小步演算法)學習小記
阿新 • • 發佈:2019-02-01
翻譯:
bsgs:
baby steps,giant steps
bsgs:
解決以下問題:
有三個整數a,b,p,其中p是質數。
求最小的自然數x,使。
根據費馬小定理,,所以只用考慮x=0~p-1
設,則x可以表示成
於是容易想到列舉 ,用個hash表存一下
接著列舉,判斷hash表裡有沒有就行了。
裸題:
【SDOI2011】計算器
Code不放了,與exbsgs類似。
exbsgs:
p不是質數。
設
此時如果b不是d的倍數且b≠1,無解,如果b=1,x=0。
可以改寫成:
此時a可能與還不互質,那就一直取gcd,設取了k次,則最後式子是:
此時互質了,直接套用bsgs,答案加個k就行了。
但是要注意一下xk的情況,這個在之前的試除就可以判掉。
Code(【SDOI2011】計算器):
裸題:
SPOJ MOD
Code:
#include<cstdio>
#include<cmath>
#include<map>
#define ll long long
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
using namespace std;
ll a, b, p;
ll ksm(ll x, ll y, const ll mo) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
ll gcd(ll x ,ll y) {
return !y ? x : gcd(y, x % y);
}
map<ll, ll> h;
ll exbsgs(ll a, ll b, ll p) {
if(b == 1) return 0;
ll k = 0, d = 1, t;
while((t = gcd(a, p)) != 1) {
if(b % t) return -1;
k ++, b /= t, p /= t, d = d * (a / t) % p;
if(b == d) return k;
}
h.clear();
ll m = sqrt(p * 1.0), a_m = ksm(a, m, p);
ll mul = b;
fo(j, 1, m) {
mul = mul * a % p;
h[mul] = j;
}
fo(i, 1, m) {
d = d * a_m % p;
if(h[d]) return i * m - h[d] + k;
}
return -1;
}
int main() {
while(1) {
scanf("%lld %lld %lld", &a, &p, &b);
if(a == 0 && b == 0 && p == 0) return 0;
ll ans = exbsgs(a, b, p);
if(ans == -1) printf("No Solution\n"); else printf("%lld\n", ans);
}
}