上一篇博文中说道了baby step giant step的方法(简称BSGS),不过对于XY mod Z = K ,若x和z并不互质,则不能直接套用BSGS的方法了。

  为什么?因为这时候不存在逆元了啊,那么怎么办呢?

  既然是x和z不互质,那么我们就想办法让他们互质,再套用BSGS的解法即可。(这就是所谓的消因子法)

代码如下:

 #include<cstdio>
#include<cstring>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
#define Maxn 40000 LL x,z,k,aa,m;
int cnt,num;
int ok; struct node
{
int idx;LL val;
}baby[Maxn]; LL ax,ay;
LL exgcd(LL a,LL b)
{
if(b==) {ax=,ay=;return a;}
LL g=exgcd(b,a%b);
LL yy=ay;
ay=ax-a/b*ay;ax=yy;
return g;
} bool cmp(node x,node y) {return x.val==y.val?x.idx<y.idx:x.val<y.val;} int ffind(LL x)
{
int head=,tail=cnt;
while(head<tail)
{
int mid=(head+tail)>>;
if(baby[mid].val==x) return baby[mid].idx;
if(baby[mid].val>x) tail=mid-;
else head=mid+;
}
if(baby[head].val==x) return baby[head].idx;
return -;
} bool init()
{
scanf("%lld%lld%lld",&x,&z,&k);
//if(==EOF) return 0;
if(x==&&z==&&k==) return ;k%=z;
LL g,bm;
bm=%z;aa=,num=;ok=;
//if(k>=z) {ok=0;return 1;}
for(int i=;i<=;i++) if(bm==k) {printf("%d\n",i);ok=;return ;}
else bm=(bm*x)%z;
while((g=exgcd(x,z))!=)
{
aa=(aa*x/g)%z,z/=g;num++;
if(k%g!=) {ok=-;break;}
k/=g;
}
return ;
} LL BSGS()
{
baby[].idx=,baby[].val=aa%z;
m=(LL)(ceil(double(sqrt((double)z))));
for(int i=;i<=m;i++) baby[i].idx=i,baby[i].val=(baby[i-].val*x)%z;
LL bm=%z,ans=-,g;
for(int i=;i<=m;i++) bm=(bm*x)%z;
g=exgcd(bm,z);
bm=ax/g; bm=(bm%(z/g)+(z/g))%(z/g);
if(bm==) bm=z/g;
sort(baby,baby+m+,cmp);cnt=;
for(int i=;i<=m;i++) if(baby[i].val!=baby[cnt].val) baby[++cnt]=baby[i];
LL tmp=k;
for(int i=;i<=m;i++)
{
int j;
if((j=ffind(tmp))!=-)
{
ans=i*m+j;
break;
}
tmp=(tmp*bm)%z;
}
return ans;
} int main()
{
while()
{
LL ans;
if(!init()) break;
if(ok==) continue;
else if(ok==-) printf("No Solution\n");
else
{
ans=BSGS();
if(ans==-) printf("No Solution\n");
else printf("%lld\n",ans+num);
}
}
return ;
}

poj3243 (二分版)

  另外,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标记。

  hash版代码如下:

 #include<cstdio>
#include<cstring>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
#define Maxn 40000
const int pp=(<<)-; LL x,z,k,aa,m;
int cnt,num;
int ok; struct node
{
int idx,nt;
LL val;
}baby[*Maxn];int len; LL ax,ay;
LL exgcd(LL a,LL b)
{
if(b==) {ax=,ay=;return a;}
LL g=exgcd(b,a%b);
LL yy=ay;
ay=ax-a/b*ay;ax=yy;
return g;
} void ins(LL now,int id)
{
int x=now&pp;
if(baby[x].idx==-) {baby[x].idx=id;baby[x].val=now;return;}
while(baby[x].val!=now&&baby[x].nt!=-) x=baby[x].nt;
if(baby[x].val==now) return;
baby[x].nt=++len;
baby[len].nt=-;baby[len].val=now;baby[len].idx=id;
} bool init()
{
scanf("%lld%lld%lld",&x,&z,&k); if(x==&&z==&&k==) return ;k%=z;
LL g,bm;
bm=%z;aa=,num=;ok=; for(int i=;i<=;i++) if(bm==k) {printf("%d\n",i);ok=;return ;}
else bm=(bm*x)%z;
while((g=exgcd(x,z))!=)
{
z/=g,aa=(aa*x/g)%z;num++;
if(k%g!=) {ok=-;break;}
k/=g;
} return ;
} int ffind(LL now)
{
int x=now&pp;
if(baby[x].idx==-) return -;
while(baby[x].val!=now&&baby[x].nt!=-) x=baby[x].nt;
if(baby[x].val!=now) return -;
return baby[x].idx;
} LL BSGS()
{
m=(LL)(ceil(double(sqrt((double)z)))); for(int i=;i<=pp;i++) baby[i].idx=baby[i].nt=-; LL now=aa%z; len=pp;
for(int i=;i<=m;i++) {ins(now,i);now=(now*x)%z;} LL bm=%z,ans=-;
for(int i=;i<=m;i++) bm=(bm*x)%z;
LL g=exgcd(bm,z);
bm=ax/g; bm=(bm%(z/g)+(z/g))%(z/g);
if(bm==) bm=z/g; LL tmp=k;
for(int i=;i<=m;i++)
{
int j;
if((j=ffind(tmp))!=-)
{
ans=i*m+j;
break;
}
tmp=(tmp*bm)%z;
}
return ans;
} int main()
{
while()
{
LL ans;
if(!init()) break;
if(ok==) continue;
else if(ok==-) printf("No Solution\n");
else
{
ans=BSGS();
if(ans==-) printf("No Solution\n");
else printf("%lld\n",ans+num);
}
}
return ;
}

poj3243 (hash版)

  在我的理解中呢,hash相当于给每个数给予一个特征,这个特征的种类有限,而且我们根据一个数可以很快知道他的特征。我们存数的事后呢,就把相同特征的存到一起。查找的时候呢,循着这个特征找,就可以很快地找到这个数了。这个特征也要定好,使得随机的数据里面用有着相同特征的个数尽量少。

2016-02-04 09:14:28

-----------------------------------------

2016-08-27 11:29:01 更新

【POJ3243】拓展BSGS(附hash版)的更多相关文章

  1. 【POJ 3243】Clever Y 拓展BSGS

    调了一周,我真制杖,,, 各种初始化没有设为1,,,我当时到底在想什么??? 拓展BSGS,这是zky学长讲课的课件截屏: 是不是简单易懂.PS:聪哥说“拓展BSGS是偏题,省选不会考,信我没错”,那 ...

  2. 数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)

    什么叫高次同余方程?说白了就是解决这样一个问题: A^x=B(mod C),求最小的x值. baby step giant step算法 题目条件:C是素数(事实上,A与C互质就可以.为什么?在BSG ...

  3. 【SPOJ】Power Modulo Inverted(拓展BSGS)

    [SPOJ]Power Modulo Inverted(拓展BSGS) 题面 洛谷 求最小的\(y\) 满足 \[k\equiv x^y(mod\ z)\] 题解 拓展\(BSGS\)模板题 #inc ...

  4. 数学:拓展BSGS

    当C不是素数的时候,之前介绍的BSGS就行不通了,需要用到拓展BSGS算法 方法转自https://blog.csdn.net/zzkksunboy/article/details/73162229 ...

  5. python实现文章或博客的自动摘要(附java版开源项目)

    python实现文章或博客的自动摘要(附java版开源项目) 写博客的时候,都习惯给文章加入一个简介.现在可以自动完成了!TF-IDF与余弦相似性的应用(三):自动摘要 - 阮一峰的网络日志http: ...

  6. [拓展Bsgs] Clever - Y

    题目链接 Clever - Y 题意 有同余方程 \(X^Y \equiv K\ (mod\ Z)\),给定\(X\),\(Z\),\(K\),求\(Y\). 解法 如题,是拓展 \(Bsgs\) 板 ...

  7. 【POJ3243】【拓展BSGS】Clever Y

    Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, ...

  8. 【HDU2815】【拓展BSGS】Mod Tree

    Problem Description   The picture indicates a tree, every node has 2 children.  The depth of the nod ...

  9. POJ 3243 Clever Y | BSGS算法完全版

    题目: 给你A,B,K 求最小的x满足Ax=B (mod K) 题解: 如果A,C互质请参考上一篇博客 将 Ax≡B(mod C) 看作是Ax+Cy=B方便叙述与处理. 我们将方程一直除去A,C的最大 ...

随机推荐

  1. 《Apache之虚拟主机的配置》——RHEL6.3

    1.安装httpd软件包: Yum install httpd 2.启动apache服务: [root@redhat Desktop]# /etc/init.d/httpd start Startin ...

  2. zedboard之ubuntu环境变量设置

    在Ubuntu中有如下几个文件可以设置环境变量 1./etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. ...

  3. WInform启动另一个项目传值

    背景:从A项目中登陆后,跳转到B项目的某个页面(B不再登陆). A项目启动进程: public Form1() { InitializeComponent(); } #region 调用进程 [Dll ...

  4. [大牛翻译系列]Hadoop(18)MapReduce 文件处理:基于压缩的高效存储(一)

    5.2 基于压缩的高效存储 (仅包括技术25,和技术26) 数据压缩可以减小数据的大小,节约空间,提高数据传输的效率.在处理文件中,压缩很重要.在处理Hadoop的文件时,更是如此.为了让Hadoop ...

  5. 三种找回 linux root密码的方法

    找回 linux root密码的三种方法 第1种方法: 1.在系统进入单用户状态,直接用passwd root去更改2.用安装光盘引导系统,进行linux rescue状态,将原来/分区挂接上来,作法 ...

  6. 通知栏发送消息Notification(可以使用自定义的布局)

    一个简单的应用场景:假如用户打开Activity以后,按Home键,此时Activity 进入-> onPause() -> onStop() 不可见.代码在此时机发送一个Notifica ...

  7. 禁用cookie后

    服务器为某个访问者创建一个内存区域,这个就是所谓的session,这个区域的存在是有时间限制的,比如30分钟,这块区域诞生的时候,服务器会给这个区域分配一个钥匙,只有使用这个钥匙才能访问这个区域,这个 ...

  8. Xaml代码格式设置

    Xaml格式化后属性分行显示的设置方法为 找到Tools->Text Editor->Xaml->Formatting->Spacing,选择Position each att ...

  9. html 布局;css3+jq 下拉菜单;table分页动态添加行;html5本地存储;简单易用的html框架

    简单好用的html框架,预览图见最后: 源码: 1.页面布局使用table: table 嵌套 +iframe 布局: 2.下拉菜单为jq+css3 动画; css input 无边框,select下 ...

  10. 【jquery】 API讲解 内部培训资料

    资料在百度云盘 一.jquery  API讲解 1.jquery  api如何使用 jquery  api http://www.hemin.cn/jq/ 2.常用api讲解 选择器: 通过$()获取 ...