POJ 3243 Clever Y | BSGS算法完全版

题目:

给你A,B,K

求最小的x满足Ax=B (mod K)


题解:

如果A,C互质请参考上一篇博客

将 Ax≡B(mod C) 看作是Ax+Cy=B方便叙述与处理.

我们将方程一直除去A,C的最大公约数进行变形,最终使得A和C互质.

将方程同除d1=gcd(A,C),得到B1=A/d1*Ax-1+C1y.有可能A和C1不互素,因此继续将方程同除d2=gcd(A,C1)得到B2=A2/d1d2*Ai-2+C2y.一直这样下去知道A和Ci互素.这里也能看出,若Bi不被gcd(A,Ci)整除则无解.

最终得到Bn=An/d1d2...dn*Ax-n+Cny,并记D=An/d1d2...dn,易证明gcd(D,Cn)=1,因此存在D的逆元,可以将最后的式子变为A x-n≡BnD-1(mod Cn),此时就能求解了.


 

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cmath>
  5 typedef long long ll;
  6 using namespace std;
  7 ll x,z,k;
  8 ll Gcd(ll x,ll y)
  9 {
 10     return y==0?x:Gcd(y,x%y);
 11 }
 12 ll exGcd(ll a,ll b,ll &x,ll &y)
 13 {
 14     if (b==0) return x=1,y=0,a;
 15     ll r=exGcd(b,a%b,y,x);
 16     y-=a/b*x;
 17     return r;
 18 }
 19 ll inv(ll a,ll m)
 20 {
 21     ll x,y;
 22     exGcd(a,m,x,y);
 23     return (x%m+m)%m;
 24 }
 25 namespace Hash
 26 {
 27     const ll N=50000;
 28     const ll H=999979;
 29     struct adj
 30     {
 31     ll nxt,v,num,val;
 32     }e[N];
 33     ll  head[H],ecnt=0;
 34     void init()
 35     {
 36     ecnt=0;
 37     memset(head,0,sizeof(head));
 38     }
 39     void insert(ll x,ll val)
 40     {
 41     ll org=x;
 42     x%=H;
 43     for (int i=head[x];i;i=e[i].nxt)
 44     {
 45         if (e[i].num==org)
 46         {
 47         e[i].val=val;
 48         return ;
 49         }
 50     }
 51     e[++ecnt].num=org;
 52     e[ecnt].val=val;
 53     e[ecnt].nxt=head[x];
 54     head[x]=ecnt;
 55     }
 56     ll query(ll x)
 57     {
 58     ll org=x;
 59     x%=H;
 60     for (int i=head[x];i;i=e[i].nxt)
 61         if (e[i].num==org) return e[i].val;
 62     return -1;
 63     }
 64 }
 65 ll BSGS(ll a,ll b,ll c)
 66 {
 67     ll cnt=0,G,d=1;
 68     while ((G=Gcd(a,c))!=1)
 69     {
 70     if (b%G!=0) return -1;
 71     cnt++,b/=G,c/=G;
 72     d=d*(a/G)%c;
 73     }
 74     b=b*inv(d,c)%c;
 75     Hash::init();
 76     ll s=sqrt(c*1.0);
 77     ll p=1;
 78     for (int i=0;i<s;i++)
 79     {
 80     if (p==b) return i+cnt;
 81     Hash::insert(p*b%c,i);
 82     p=p*a%c;
 83     }
 84     ll q=p,t;
 85     for (int i=s;i-s+1<=c-1;i+=s)
 86     {
 87     t=Hash::query(q);
 88     if (t!=-1) return i-t+cnt;
 89     q=q*p%c;
 90     }
 91     return -1;
 92 }
 93 int check()
 94 {
 95     for (ll i=0,j=1;i<=10;i++)
 96     {
 97     if (j==k)
 98     {
 99         printf("%lld\n",i);
100         return 1;
101     }
102     j=j*x%z;
103     }
104     if (x==0)
105     {
106     puts("No Solution");
107     return 1;
108     }
109     return 0;
110 }
111 int main()
112 {
113     while (scanf("%lld%lld%lld",&x,&z,&k) && x+z+k>0)
114     {
115     x%=z,k%=z;
116     if (check()) continue;
117     ll ans=BSGS(x,k,z);
118     if (ans==-1) puts("No Solution");
119     else printf("%lld\n",ans);
120     }
121     return 0;
122 }

 

posted @ 2017-11-29 17:25  MSPqwq  阅读(150)  评论(0编辑  收藏  举报