BZOJ1467: Pku3243 clever Y
解方程$a^x\equiv b (mod c)$。
扩展bsgs。利用结论:$d=(a,c),a=d*x,b=d*y,c=d*z$,则$x*d\equiv y*d (\mod z*d)$ 等价于 $x \equiv y (mod z)$。
先把$c$消$(a,c)$直到$(a,c)=1$,同时b也消,方程左边也消,假设消了$cnt$次,那么方程就等价于$p*a^{x-cnt} \equiv B (\mod C)$,其中$p$是拿$a^{cnt}$一起消的结果。然后就用普通bsgs即可。
由于这样算出来的答案强制$>=cnt$,因此要先暴力判断$log_2 c$个数是否符合题意。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<map> 6 #include<math.h> 7 //#include<time.h> 8 //#include<complex> 9 #include<algorithm> 10 using namespace std; 11 12 int a,b,c; 13 14 int gcd(int a,int b) {return b?gcd(b,a%b):a;} 15 int exgcd(int a,int b,int &x,int &y) 16 { 17 if (!b) {x=1; y=0; return a;} 18 int d=exgcd(b,a%b,y,x); y-=a/b*x; 19 return d; 20 } 21 int inv(int a,int p) 22 { 23 int x,y,d=exgcd(a,p,x,y); 24 return d==1?(x+p)%p:-1; 25 } 26 27 map<int,int> mp; 28 int exbsgs(int a,int b,int c) 29 { 30 for (int i=0,t=1;i<32;i++,t=1ll*t*a%c) if (t==b) return i; 31 int d=1,cnt=0,tmp; 32 while ((tmp=gcd(a,c))!=1) 33 { 34 if (b%tmp) return -1; 35 b/=tmp; c/=tmp; d=1ll*d*(a/tmp)%c; cnt++; 36 } 37 int m=sqrt(c)+1,e=1; mp.clear(); 38 for (int i=0;i<m;i++) {if (!mp.count(e)) mp[e]=i; e=1ll*e*a%c;} 39 int p=inv(e,c); b=1ll*b*inv(d,c); 40 for (int i=0;i<m;i++) 41 { 42 if (mp.count(b)) return i*m+mp[b]+cnt; 43 b=1ll*b*p%c; 44 } 45 return -1; 46 } 47 48 int main() 49 { 50 while (~scanf("%d%d%d",&a,&c,&b) && (a || b || c)) 51 { 52 int ans=exbsgs(a,b,c); 53 printf(ans==-1?"No Solution\n":"%d\n",ans); 54 } 55 return 0; 56 }