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\n");
else printf("%I64d\n",x*m+y);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。