BZOJ 3239 Discrete Logging BSGS

题意:链接

方法: BSGS

解析:

大爷讲完BSGS,太神辣orz。

这些数论刷的要死要活的。

这是一道裸BSGS问题。

求方程A^x=B(mod C)的最小非负整数x。

暴枚是不可以都通过的,其次它是多组数据,所以怎么想呢。

我们不妨把整个问题分成两半,对于前一半,我们把值先算出来扔到哈希表里,然后后一半再找其能够凑成答案的值是否在哈希表中,如果在哈希表中,则第一个被找的一定是最小的。

这个算法还是很好懂的,C是质数的话也好分析也好写。

代码:

#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mod 140345
using namespace std;
typedef long long ll;
int head[mod+10];
ll c,a,b,ans;
int cnt;
struct node
{
    int from,to,next;
    ll val;
}edge[mod+10];
ll get_inv(ll x,ll y)
{
    ll ret=1;
    while(y)
    {
        if(y&1)ret=(ret*x)%c;
        x=(x*x)%c;
        y>>=1;
    }
    return ret;
}
void init()
{
    memset(head,-1,sizeof(head));
    cnt=1;
}
void edgeadd(int from,int to,ll val)
{
    edge[cnt].from=from,edge[cnt].to=to,edge[cnt].val=val;
    edge[cnt].next=head[from];
    head[from]=cnt++;
}
void BSGS(int A,int B,int C)
{
    //A^x=B(mod C);
    int m=(int)ceil(sqrt(C));
    ll k=1;
    edgeadd(1,0,1);
    for(int i=1;i<m;i++)
    {
        k=(k*A)%C;
        int flag=0;
        for(int j=head[k%mod];j!=-1;j=edge[j].next)
        {
            int val=edge[j].val;
            if(val==k){flag=1;break;}
        }
        if(!flag)edgeadd(k%mod,i,k);
    }
    k=(k*A)%C;
    ll D=1;
    ll inv=get_inv(D,C-2);
    ll tmp=B*inv%C;
    ans=-1;
    for(int j=head[tmp%mod];j!=-1;j=edge[j].next)
    {
        int val=edge[j].val;
        if(val==tmp)
        {
            ans=edge[j].to;break;
        }
    }
    if(ans!=-1){printf("%lld\n",ans);return;}
    for(int i=1;i<=m;i++)
    {
        D=D*k%C;
        inv=get_inv(D,C-2);
        tmp=B*inv%C;
        for(int j=head[tmp%mod];j!=-1;j=edge[j].next)
        {
            int val=edge[j].val;
            if(val==tmp)
            {
                ans=edge[j].to+i*m;
                break;
            }
        }
        if(ans!=-1){printf("%lld\n",ans);return;}
    }
}
int main()
{
    while(~scanf("%lld%lld%lld",&c,&a,&b))
    {
        init();
        BSGS(a,b,c);
        if(ans==-1)puts("no solution");
    }
}

你可能感兴趣的:(算法,数据,C语言,logging,X)