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 }
View Code

 

posted @ 2018-02-26 11:04  Blue233333  阅读(171)  评论(0编辑  收藏  举报