1. 程式人生 > >bzoj 3239: Discrete Logging【BSGS】

bzoj 3239: Discrete Logging【BSGS】

bzoj bsp i++ urn blog () pac a* scan

BSGS的板子題
此時 \( 0 \leq x \leq p-1 \)
設 \( m=\left \lceil \sqrt{p} \right \rceil ,x=i*m-j \)這裏-的作用是避免逆元
於是可以把式子變形成這樣:\( a^{im}\equiv ba^j(mod p) \)
枚舉右邊\( 0 \leq j <m \) ,用map或者hash以模數為下標來存每一個j
枚舉左邊\( 0 \leq i <m \) ,在map或者hash中查找對應的模數

#include<iostream>
#include<cstdio>
#include<map>
#include<cmath> using namespace std; long long a,b,p; map<long long,long long>mp; long long ksm(long long a,long long b,long long p) { long long r=1ll; a%=p; while(b) { if(b&1) r=r*a%p; a=a*a%p; b>>=1; } return r; } int
main() { while(~scanf("%lld%lld%lld",&p,&a,&b)) { a%=p; if(!a&&!b) { puts("1"); continue; } if(!a) { puts("no solution"); continue; } if(b==1) { puts("0"
); continue; } mp.clear(); int m=ceil(sqrt(p)),t=b,f=0; for(int i=0;i<m;i++) { mp[t]=i; t=(long long)t*a%p; } int g=ksm(a,m,p); t=(long long)g%p; for(int i=1;i<=m+1;i++) { if(mp.count(t)) { f=1; printf("%lld\n",i*m-mp[t]); break; } t=(long long)t*g%p; } if(!f) puts("no solution"); } return 0; }

bzoj 3239: Discrete Logging【BSGS】