详解
下面的模板中是,调用函数时是A,B,C A^x=B(mod C)
poj3243(模板题)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long LL;
struct HashMap
{//哈希表
    static const int Hash=999917,maxn=46340;
    int num,link[Hash],son[maxn+5],next[maxn+5],w[maxn+5];
    int top,Stack[maxn+5];
    void clear()
    {//清空表
        num=0;
        while(top)
            link[Stack[top--]]=0;
    }
    void add(int x,int y)
    {//添加键值元素
        son[++num]=y;
        next[num]=link[x];
        w[num]=INF;
        link[x]=num;
    }
    bool count(int y)
    {//判断表中是否有对应值
        int x=y%Hash;
        for(int j=link[x];j;j=next[j])
            if(y==son[j])
                return true;
        return false;
    }
    int &operator [](int y)
    {//获取键的对应值
        int x=y%Hash;
        for(int j=link[x];j;j=next[j])
            if(y==son[j])
                return w[j];
        add(x,y);
        Stack[++top]=x;
        return w[num];
    }
}hashMap;
int GCD(int a,int b)
{
    if(b==0)
        return a;
    return GCD(b,a%b);
}
int extendedGCD(int x,int y,int &a,int &b)
{
    if(y==0)
    {
        a=1;
        b=0;
        return x;
    }
    int temp;
    int gcd=extendedGCD(y,x%y,a,b);
    temp=a;
    a=b;
    b=temp-x/y*b;
    return gcd;
}
int extendBSGS(int A,int B,int C)
{
    //三种特判
    if(C==1)
    {
        if(!B)
            return A!=1;
        return -1;
    }
    if(B==1)
    {
        if(A)
            return 0;
        return -1;
    }
    if(A%C==0)
    {
        if(!B)
            return 1;
        return -1;
    }

    int gcd=GCD(A,C);
    int D=1,num=0;
    while(gcd!=1)
    {//把A,C变成(A,C)=1为止
        if(B%gcd)
            return -1;
        B/=gcd;//从B中约去因子
        C/=gcd;//约C中约去因子
        D=((LL)D*A/gcd)%C;//将多出的乘给D
        num++;//统计约去次数
        gcd=GCD(A,C);
    }
    int now=1;
    for(int i=0;i<=num-1;i++){//枚举0~num-1
        if(now==B)
            return i;
        now=((LL)now*A)%C;
    }
    hashMap.clear();
    int Size=ceil(sqrt(C)),Base=1;
    for(int i=0;i<=Size-1;i++)
    {//将A^j存进哈希表
        hashMap[Base]=min(hashMap[Base],i);//存储答案最小的
        Base=((LL)Base*A)%C;
    }
    for(int i=0;i<=Size-1;i++)
    {//扩展欧几里得求A^j
        int x,y;
        int gcd=extendedGCD(D,C,x,y);//求出x、y
        x=((LL)x*B%C+C)%C;
        if(hashMap.count(x))
            return i*Size+hashMap[x]+num;//加回num
        D=((LL)D*Base)%C;
    }
    return -1;//无解
}
int main()
{
    int X,K,Z;
    while(scanf("%d%d%d",&X,&Z,&K)!=EOF&&(X+Z+K)){
        int res=extendBSGS(X,K,Z);
        if(res==-1)
            printf("No Solution\n");
        else
            printf("%d\n",res);
    }
    return 0;
}

poj2417(套模板)
注意输入顺序

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long LL;
struct HashMap
{//哈希表
    static const int Hash=999917,maxn=46340;
    int num,link[Hash],son[maxn+5],next[maxn+5],w[maxn+5];
    int top,Stack[maxn+5];
    void clear()
    {//清空表
        num=0;
        while(top)
            link[Stack[top--]]=0;
    }
    void add(int x,int y)
    {//添加键值元素
        son[++num]=y;
        next[num]=link[x];
        w[num]=INF;
        link[x]=num;
    }
    bool count(int y)
    {//判断表中是否有对应值
        int x=y%Hash;
        for(int j=link[x];j;j=next[j])
            if(y==son[j])
                return true;
        return false;
    }
    int &operator [](int y)
    {//获取键的对应值
        int x=y%Hash;
        for(int j=link[x];j;j=next[j])
            if(y==son[j])
                return w[j];
        add(x,y);
        Stack[++top]=x;
        return w[num];
    }
}hashMap;
int GCD(int a,int b)
{
    if(b==0)
        return a;
    return GCD(b,a%b);
}
int extendedGCD(int x,int y,int &a,int &b)
{
    if(y==0)
    {
        a=1;
        b=0;
        return x;
    }
    int temp;
    int gcd=extendedGCD(y,x%y,a,b);
    temp=a;
    a=b;
    b=temp-x/y*b;
    return gcd;
}
int extendBSGS(int A,int B,int C)
{
    //三种特判
    if(C==1)
    {
        if(!B)
            return A!=1;
        return -1;
    }
    if(B==1)
    {
        if(A)
            return 0;
        return -1;
    }
    if(A%C==0)
    {
        if(!B)
            return 1;
        return -1;
    }

    int gcd=GCD(A,C);
    int D=1,num=0;
    while(gcd!=1)
    {//把A,C变成(A,C)=1为止
        if(B%gcd)
            return -1;
        B/=gcd;//从B中约去因子
        C/=gcd;//约C中约去因子
        D=((LL)D*A/gcd)%C;//将多出的乘给D
        num++;//统计约去次数
        gcd=GCD(A,C);
    }
    int now=1;
    for(int i=0;i<=num-1;i++){//枚举0~num-1
        if(now==B)
            return i;
        now=((LL)now*A)%C;
    }
    hashMap.clear();
    int Size=ceil(sqrt(C)),Base=1;
    for(int i=0;i<=Size-1;i++)
    {//将A^j存进哈希表
        hashMap[Base]=min(hashMap[Base],i);//存储答案最小的
        Base=((LL)Base*A)%C;
    }
    for(int i=0;i<=Size-1;i++)
    {//扩展欧几里得求A^j
        int x,y;
        int gcd=extendedGCD(D,C,x,y);//求出x、y
        x=((LL)x*B%C+C)%C;
        if(hashMap.count(x))
            return i*Size+hashMap[x]+num;//加回num
        D=((LL)D*Base)%C;
    }
    return -1;//无解
}
int main()
{
    int P,B,N;
    while(scanf("%d%d%d",&P,&B,&N)!=EOF)
    {
        int res=extendBSGS(B,N,P);
        if(res==-1)
            printf("no solution\n");
        else
            printf("%d\n",res);
    }
    return 0;
}

hdu 2815
换了一个模板,之前的那个,可能是数据范围的原因,一直WA。
关键还是建立方程,直接套模板即可。

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int MAXN=131071;
struct HashNode
{
    ll data, id, next;
};
HashNode hash[MAXN<<1];
bool flag[MAXN<<1];
ll top;
void Insert (ll a,ll b )
{
    ll k=b&MAXN;
    if (flag[k]==false)
    {
        flag[k]=true;
        hash[k].next=-1;
        hash[k].id=a;
        hash[k].data=b;
        return;
    }
    while(hash[k].next!=-1)
    {
        if(hash[k].data==b)
            return;
        k=hash[k].next;
    }
    if(hash[k].data==b)
        return;
    hash[k].next=++top;
    hash[top].next=-1;
    hash[top].id=a;
    hash[top].data=b;
}
ll Find(ll b)
{
    ll k=b&MAXN;
    if(flag[k]==false)
        return -1;
    while(k!=-1)
    {
        if(hash[k].data==b)
            return hash[k].id;
        k=hash[k].next;
    }
    return -1;
}
ll gcd(ll a,ll b)
{
    return b?gcd (b,a%b):a;
}
ll ext_gcd(ll a,ll b,ll& x,ll& y )
{
    ll t,ret;
    if (b==0)
    {
        x=1,y=0;
        return a;
    }
    ret=ext_gcd(b,a%b,x,y);
    t=x,x=y,y=t-a/b*y;
    return ret;
}
ll mod_exp(ll a,ll b,ll n )
{
    ll ret=1;
    a=a%n;
    while(b>=1)
    {
        if(b&1)
            ret=ret*a%n;
        a=a*a%n;
        b>>=1;
    }
    return ret;
}
ll BabyStep_GiantStep(ll A,ll B,ll C)
{
    top=MAXN;
    B%=C;
    ll tmp=1,i;
    for(i=0;i<=100;tmp=tmp*A%C,i++)
        if (tmp==B%C)
            return i;
    ll D=1,cnt=0;
    while((tmp=gcd(A,C))!=1 )
    {
        if(B%tmp)
            return -1;
        C/=tmp;
        B/=tmp;
        D=D*A/tmp%C;
        cnt++;
    }
    ll M=(ll)ceil(sqrt(C+0.0));
    for (tmp=1,i=0;i<=M;tmp=tmp*A%C,i++)
        Insert(i,tmp);
    ll x,y,K=mod_exp(A,M,C);
    for(i=0;i<=M;i++)
    {
        ext_gcd(D,C,x,y); // D * X = 1 ( mod C )
        tmp=((B*x)%C+C)%C;
        if((y=Find(tmp))!=-1)
            return i * M + y + cnt;
        D=D*K%C;
    }
    return -1;
}
int main()
{
    ll K,P,N;
    while(scanf("%lld%lld%lld",&K,&P,&N)!=EOF)
    {
        memset(flag,0,sizeof(flag));
        if(N>P)//坑
        {
            printf("Orz,I can’t find D!\n");
            continue;
        }
        ll tmp=BabyStep_GiantStep(K,N,P);
        if (tmp==-1)
            printf("Orz,I can’t find D!\n");
        else
            printf("%I64d\n",tmp);
    }
    return 0;
}