不理解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; }
该题和POJ 2417,HDU 2815 一样,代码稍微改改就能AC。
不过不同的是,HDU 2815 若B>=C,则要判断无解。而不是像POJ这两道题,要先B%C一下。