Poj2417 大步小步算法

题目

poj2417
Given a prime P,2<=P<231 , an integer B,2<=B<P , and an integer N,1<=N<P , compute the discrete logarithm of N , base B , modulo P . That is, find an integer L such that BL=N(modP)

题解

我们设 L=ktm ,其中 t=L,0<=m<t 。那么 BL=N(modP) 就等价于 Bktm=N(modP) BktN1=Bm(modP) 。我们可以先预处理出所有的 Bi(0<=i<t) 记录在一个hash表里,然后枚举k,计算 BktN1 的值,在hash表里找是否有符和条件的m,若有则 ktm 就是答案之一。所有答案中取最小的一个即可。这就是大步小步算法。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

#define INF 1000000007
#define mo 1000007
typedef long long ll;
struct node{
    ll m,data;
    int next;
}hash[1000000];
ll t,m,k,p,a,b,x,y,first[mo+1],tot,ans; 

void insert(ll x,ll m){
    int y=x%mo;
    hash[++tot].data=x;
    hash[tot].next=first[y];
    hash[tot].m=m;
    first[y]=tot;
}

void find(ll x,ll k){
    ll y=x%mo;
    for(int i=first[y];i;i=hash[i].next){
        if(hash[i].data==x&&k*t-hash[i].m>=0)
        ans=min(ans,k*t-hash[i].m);
    }
}

ll power(ll a,ll b,ll p){
    ll tmp=1;
    while(b){
        if(b&1)tmp=tmp*a%p;
        a=a*a%p; b/=2;
    }
    return tmp;
}

int main(){
    while(~scanf("%lld%lld%lld",&p,&a,&b)){
        memset(first,0,sizeof(first));
        t=(ll)sqrt(p)+1;
        x=1; b=power(b,p-2,p);
        for(int i=0;i<=t;i++){
            insert(x,i);
            x=x*a%p;
        }
        ans=INF;
        x=power(a,t,p); y=1;
        for(k=0;k<=t;k++){
            find(y*b%p,k);
            y=y*x%p;
        }
        if(ans==INF)puts("no solution");
        else printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(Poj2417 大步小步算法)