题意:
给p,b,n求最小的l使b^l==n(mod p)。
题意:
相当于在0~p-1内搜索l满足同余式,baby_step,giant_step相当于分块的二分搜索,设m=sqrt(p), 则将p分为m*m,在m块内每块进行m个数的二分搜索。
代码:
//poj 2417 //sep9 #include <iostream> #include <cmath> #include <algorithm> using namespace std; const int maxN=100000; typedef long long ll; struct Node { int ids; ll v; }baby[maxN]; int cmp(Node x,Node y) { if(x.v!=y.v) return x.v<y.v; return x.ids<y.ids; } ll pow_mod(ll a,ll b,ll mod) { ll ans=1; while(b){ if(b&1) ans=(ans*a)%mod; a=(a*a)%mod; b>>=1; } return ans; } int bsearch(int len,ll v) { int l=0,r=len,mid; while(l<r){ mid=(l+r)/2; if(baby[mid].v==v) return baby[mid].ids; else if(baby[mid].v<v) l=mid+1; else r=mid; } return -1; } int main() { ll p,b,n; while(scanf("%I64d%I64d%I64d",&p,&b,&n)==3){ int m=(int)ceil(sqrt((p-1)*1.0)); baby[0].ids=0,baby[0].v=1; for(int i=1;i<m;++i){ baby[i].ids=i; baby[i].v=(baby[i-1].v*b)%p; } sort(baby,baby+m,cmp); int cnt=1; for(int i=1;i<m;++i) if(baby[i].v!=baby[i-1].v) baby[cnt++]=baby[i]; ll bm=pow_mod(pow_mod(b,p-2,p),m,p); int ans=-1; for(int i=0;i<m;++i){ int j=bsearch(cnt,n); if(j!=-1){ ans=i*m+j; break; } n=(n*bm)%p; } if(ans<0) puts("no solution"); else printf("%d\n",ans); } return 0; }
时间: 2024-11-08 06:37:04