BZOJ 3239 Discrete Logging

Posted on 2016-05-20 19:55  ziliuziliu  阅读(131)  评论(0编辑  收藏  举报

BSGS。细节蛮多的。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 100500
using namespace std;
struct hhh
{
    long long id,num;
}hash[maxn];
long long b,n,p,lim;
bool cmp(hhh x,hhh y)
{
    if (x.num!=y.num) 
        return x.num<y.num;
    return x.id<y.id;
}
inline long long mul(long long a,long long b)
{
    long long d=(long long)floor(a*(double)b/p+0.5);
    long long ret=a*b-d*p;
    if (ret<0) ret+=p;
    return ret;
}
inline long long mull(long long a,long long b)
{
    long long ans=1,base=a;
    while (b)
    {
        if (b&1) ans=mul(ans,base)%p;
        base=mul(base,base)%p;
        b>>=1;
    }
    return ans;
}
long long found(long long now,long long x)
{
    long long ans;
    while (hash[now].num%p==x%p)
    {
        ans=hash[now].id;
        now--;
    }
    return ans;
}
long long find(long long x)
{
    long long left=0,right=lim-1;
    while (left<=right)
    {
        long long mid=(left+right)>>1;
        long long regis1=hash[mid].num%p,regis2=x%p;
        if (regis1==regis2) 
        {
            return found(mid,x);
        } 
        else if (regis1>regis2) right=mid-1;
        else left=mid+1;
    }
    return -1;
}
int main()
{
    while (scanf("%lld%lld%lld",&p,&b,&n)!=EOF)
    {
        long long flag=0;
        long long inv=mull(b,p-2)%p,base=n%p;lim=ceil(sqrt(p));
        for (long long i=0;i<lim;i++)
        {
            hash[i].id=i;
            hash[i].num=base%p;
            base=mul(base,inv)%p;    
        }
        sort(hash,hash+lim,cmp);
        base=1;long long regis=mull(b,lim)%p;
        for (long long i=0;i<=lim;i++)
        {
            long long rr=find(base);
            if ((rr!=-1) && (flag==0))
            {
                printf("%d\n",mul(i,lim)+rr);
                flag=1;
            }
            base=mul(base,regis)%p;
        }
        if (flag==0) printf("no solution\n");
    }
    return 0;
}