POJ 3243 Clever Y (求解高次同余方程A^x=B(mod C) Baby Step Giant Step算法)

不理解Baby Step Giant Step算法,请戳:

http://www.cnblogs.com/chenxiwenruo/p/3554885.html

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define SIZE 99991
/*
POJ 3243
AC
求解同余方程:
A^x=B(mod C)
*/
using namespace std;
struct HashTable{
    int key[SIZE];  //对应A^i
    int val[SIZE];  //对应i
    void init(){
        memset(key,-1,sizeof(key));
        memset(val,-1,sizeof(val));
    }
    int hfind(int k){
        int kk=k%SIZE;
        while(key[kk]!=k && key[kk]!=-1){
            kk=(kk+1)%SIZE; //原先写成了kk=(kk+1)&SIZE;导致一直TLE。。。
        }
        return val[kk];
    }
    void hinsert(int v,int k){
        int kk=k%SIZE;
        while(key[kk]!=-1 && key[kk]!=k){
            kk=(kk+1)%SIZE;
        }
        if(key[kk]==-1){
            key[kk]=k;
            val[kk]=v;
        }
    }
}h;

int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    int d=exgcd(b,a%b,x,y);
    int tmp=x;
    x=y;
    y=tmp-a/b*y;
    return d;
}

//求解ax=b(mod c),
int solvex(int a,int b,int c){
    int x,y;
    int d;
    d=exgcd(a,c,x,y);
    //注意这里要强制转换成long long,不然x*b会超出int范围
    x=((long long)x*b%c+c)%c;
    //x=((long long)x*(b/d)%(c/d)+c/d)%(c/d); //实际应该是这样,但由于传的参数D,B,C中,D、C互质,d=1。
    return x;
}
long long quickPow(long long a,int b,int mod){
    long long ret=1%mod;
    a=a%mod;
    while(b){
        if(b&1)
            ret=(ret*a)%mod;
        a=(a*a)%mod;
        b=b>>1;
    }
    return ret;
}
int BabyStep(int A,int B,int C){
    B=B%C;  //注意这里先要将B对C取模
    h.init();
    int d=0;
    long long D=1%C,buf=D;
    for(int i=0;i<=100;buf=buf*A%C,++i){
        if(buf==B)
            return i;
    }
    int tmp;
    while((tmp=gcd(A,C))!=1){
        if(B%tmp)
            return -1;
        d++;
        B=B/tmp;
        C=C/tmp;
        D=D*A/tmp%C;
    }
    int m=(int)ceil(sqrt((double)C));
    buf=1%C;
    for(int i=0;i<m;buf=buf*A%C,++i){
        h.hinsert(i,(int)buf);
    }
    long long K=quickPow((long long)A,m,C);
    for(int i=0;i<m;D=D*K%C,++i){
        int ans=solvex((int)D,B,C);
        int j=h.hfind(ans);
        if(j!=-1)
            return i*m+j+d;
    }
    return -1;
}
int main()
{
    int A,B,C;
    while(scanf("%d%d%d",&A,&C,&B)!=EOF){
        if(A==0 && B==0 && C==0)
            break;
        int ans=BabyStep(A,B,C);
        if(ans==-1)
            printf("No Solution
");
        else
            printf("%d
",ans);
    }
    return 0;
}
View Code

该题和POJ 2417,HDU 2815 一样,代码稍微改改就能AC。

不过不同的是,HDU 2815  若B>=C,则要判断无解。而不是像POJ这两道题,要先B%C一下。

原文地址:https://www.cnblogs.com/chenxiwenruo/p/3554894.html