poj_2417 (baby_step,giant_step算法)

最近要把大工的线段树专题补完,然后写一个线段树的总结。。。 

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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-08-01 18:58  hqwhqwhq  阅读(335)  评论(0编辑  收藏  举报