http://poj.org/problem?id=3243

题意:给定X,Z,K,求一个最小的Y满足XY mod Z = K。

 

关于拓展BSGS的详细解释我写了一篇博文:http://www.cnblogs.com/KonjakJuruo/p/5178600.html


题解:BSGS的拓展版本(因为X和Z不一定互质)。这道题挺坑的,如果K>=Z不是输出无解而是让K%=Z。

算是BSGS的模板题,我打了两种版本,就是二分查找和hash。对比两次提交来看,二分省空间,耗时间;Hash省时间,耗空间。

 

  另外,find部分可以不用二分,而用hash解决。感觉大部分情况下还是hash比较快,但是比较耗空间。

  把你需要存的数,即x的0~m次方算出来,假设是t,我们设m=1<<16-1,然后用t异或^m得nt(就是取t二进制后的15位进行hash),然后存到hash表里面去。如果t的位置目前没有存数,那么我们就直接存到hash[t]上去,如果t位置已经存了数(因为后15位为t的可能有多种情况),我们就在len除增加一个位置,把nt存到那里面去,然后hash[t].next=len,把位置记录下来,这应该就相当于一条链了。查找的时候循着这条链找下去即可,链的尽头的next用-1标记。

——引用自http://www.cnblogs.com/Konjakmoyu/p/5180458.html

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<cmath>
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 typedef long long LL;
 10 const int N=40000;
 11 bool bk;
 12 LL X,Z,K,a,b,c,m,k,sum,am,bl;
 13 struct node{
 14     LL d,id;
 15 }bit[N],p[N];
 16 
 17 bool cmp(node x,node y){
 18     if(x.d!=y.d) return x.d<y.d;
 19     return x.id<y.id;
 20 }
 21 
 22 LL gcd(LL u,LL v)
 23 {
 24     if(v==0) return u;
 25     return gcd(v,u%v);
 26 }
 27 
 28 LL find(LL x)
 29 {
 30     int l=0,r=bl;
 31     while(l<=r)
 32     {
 33         int mid=(l+r)>>1;
 34         if(bit[mid].d==x) return bit[mid].id;
 35         if(bit[mid].d>x) r=mid-1;
 36         if(bit[mid].d<x) l=mid+1;
 37     }
 38     return -1;
 39 }
 40 
 41 void exgcd(LL u,LL v,LL &x,LL &y)
 42 {
 43     if(v==0) {x=1,y=0;return ;}
 44     LL tx,ty;
 45     exgcd(v,u%v,tx,ty);
 46     x=ty;y=tx-(u/v)*ty;
 47     return;
 48 }
 49 
 50 LL BSGS()
 51 {
 52     LL t,g,x,y,pm;
 53     a=X;b=K;c=Z;k=1;sum=0;bk=1;bl=0;t=1%c;
 54     for(int i=0;i<=100;i++){//避免a的负数次方
 55         if(t==b) return i;
 56         t=t*a%c;
 57     }
 58     while((g=gcd(X,c))!=1)
 59     {
 60         k=(k*X/g)%c;//k记得要mod,否则溢出
 61         c/=g;
 62         if(b%g) return -1;
 63         b/=g;
 64         sum++;
 65     }
 66     m=(LL)(ceil((double)sqrt((double)c)));//要约分之后再求m
 67     p[0].d=k%c;
 68     p[0].id=0;
 69     pm=1;//pm是不用*k的
 70     for(int i=1;i<=m;i++) 
 71         p[i].d=p[i-1].d*a%c,pm=pm*a%c,p[i].id=i;
 72     sort(p,p+1+m,cmp);
 73     bit[0]=p[0];bl=0;
 74     for(int i=1;i<=m;i++)
 75     {
 76         if(p[i].d!=p[i-1].d) bit[++bl]=p[i];
 77     }
 78     exgcd(pm,c,x,y);
 79     am=(x%c+c);//避免am=0
 80     
 81     t=b;
 82     x=find(b);
 83     if(x!=-1) return x;
 84     for(int i=1;i<=bl;i++)
 85     {
 86         t*=am;t%=c;
 87         x=find(t);
 88         if(x!=-1)
 89             return i*m+x;
 90     }
 91     return -1;
 92 }
 93 
 94 int main()
 95 {
 96     // freopen("a.in","r",stdin);
 97     // freopen("a.out","w",stdout);
 98     while(1)
 99     {
100         scanf("%I64d%I64d%I64d",&X,&Z,&K);
101         if(!X && !Z && !K) return 0;
102         K%=Z;
103         LL ans=BSGS();
104         if(ans!=-1) printf("%I64d\n",ans+sum);
105         else printf("No Solution\n");
106     }
107     return 0;
108 }
BSGS-二分

相关文章: