http://blog.csdn.net/ACM_cxlove?viewmode=contents 附上cxlove大神的博客,这里面已经讲的很明白了。
感觉baby_step,giant_step算法比较好理解,暴力的复杂度被优化到了o(sqrt(n)),然后匹配的复杂度,我是用set写的,复杂度就是o(sqrt(n)*log(sqrt(n)))。
下面直接附上代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <vector> #define FOR(i,x,y) for(int i = x;i < y;i ++) #define IFOR(i,x,y) for(int i = x;i > y;i --) #define ll long long using namespace std; typedef pair<ll,int> pii; ll p,b,n,m,num[1<<16],x,y; ll quickpow(ll a,ll n,ll m){ ll ans=1; while(n){ if(n&1) ans = (ans*a)%m; a = (a*a)%m; n>>=1; } return ans; } int main() { //freopen("test.in","r",stdin); while(~scanf("%I64d%I64d%I64d",&p,&b,&n)){ map <ll,int> s; set <ll> q; m = (ll)sqrt(1.0*p)+1; num[0] = 1; q.insert(num[0]); s[num[0]] = 0; FOR(i,1,m){ num[i] = num[i-1]*b; num[i] %= p; q.insert(num[i]); s.insert(pair<ll,int> (num[i],i)); } bool flag = false; FOR(i,0,m){ ll temp = p-1-i*m; if(temp < 0) break; temp = quickpow(b,temp,p); temp = (temp*n)%p; set <ll>::iterator it; it = q.find(temp); if(it != q.end()){ y = (*it); y = s[y]; x = i; flag = true; break; } } if(!flag) printf("no solution "); else printf("%I64d ",x*m+y); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。