【POJ3243】拓展BSGS(附hash版)
上一篇博文中说道了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版)的更多相关文章
- 【POJ 3243】Clever Y 拓展BSGS
调了一周,我真制杖,,, 各种初始化没有设为1,,,我当时到底在想什么??? 拓展BSGS,这是zky学长讲课的课件截屏: 是不是简单易懂.PS:聪哥说“拓展BSGS是偏题,省选不会考,信我没错”,那 ...
- 数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)
什么叫高次同余方程?说白了就是解决这样一个问题: A^x=B(mod C),求最小的x值. baby step giant step算法 题目条件:C是素数(事实上,A与C互质就可以.为什么?在BSG ...
- 【SPOJ】Power Modulo Inverted(拓展BSGS)
[SPOJ]Power Modulo Inverted(拓展BSGS) 题面 洛谷 求最小的\(y\) 满足 \[k\equiv x^y(mod\ z)\] 题解 拓展\(BSGS\)模板题 #inc ...
- 数学:拓展BSGS
当C不是素数的时候,之前介绍的BSGS就行不通了,需要用到拓展BSGS算法 方法转自https://blog.csdn.net/zzkksunboy/article/details/73162229 ...
- python实现文章或博客的自动摘要(附java版开源项目)
python实现文章或博客的自动摘要(附java版开源项目) 写博客的时候,都习惯给文章加入一个简介.现在可以自动完成了!TF-IDF与余弦相似性的应用(三):自动摘要 - 阮一峰的网络日志http: ...
- [拓展Bsgs] Clever - Y
题目链接 Clever - Y 题意 有同余方程 \(X^Y \equiv K\ (mod\ Z)\),给定\(X\),\(Z\),\(K\),求\(Y\). 解法 如题,是拓展 \(Bsgs\) 板 ...
- 【POJ3243】【拓展BSGS】Clever Y
Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, ...
- 【HDU2815】【拓展BSGS】Mod Tree
Problem Description The picture indicates a tree, every node has 2 children. The depth of the nod ...
- POJ 3243 Clever Y | BSGS算法完全版
题目: 给你A,B,K 求最小的x满足Ax=B (mod K) 题解: 如果A,C互质请参考上一篇博客 将 Ax≡B(mod C) 看作是Ax+Cy=B方便叙述与处理. 我们将方程一直除去A,C的最大 ...
随机推荐
- iOS获取汉字的拼音
在iOS开发中经常涉及到汉字的排序,最常见的就是需要根据首字母的字符顺序排列,比如常见的通讯录等.总结出来,大致可以分为两种方法,其中参考文献[1]中提供的方法十分复杂,利用查表的方法是先,并且代码量 ...
- Oracle 表的连接方式(1)-----Nested loop join和 Sort merge join
关系数据库技术的精髓就是通过关系表进行规范化的数据存储,并通过各种表连接技术和各种类型的索引技术来进行信息的检索和处理. 表的三种关联方式: nested loop:从A表抽一条记录,遍历B表查找匹配 ...
- 基于 WebAPI 的 API 实现
本文基于 WebAPI OData (微软发起的一个格式标准,其中一个比较有意思的是可以直接在 Excel 中填入 API 就可以展示了) Swashbuckle.OData(把 API 生成一个测试 ...
- Oracle 中的replace函数的应用
replace 函数用法如下: replace('将要更改的字符串','被替换掉的字符串','替换字符串') oracle 中chr()函数 CHR() --将ASCII码转换为字符 语法CHR(nu ...
- 部署keepalived
下载 keepalived-1.1.20.tar.gz tar -xvf keepalived-1.1.20.tar.gz [root@yoon export]# cd keepalived-1. ...
- ArcGIS For JavaScript API 默认参数
“esri.config”的是在1.3版中的的“esriConfig”的替代品.如果您使用的是1.2或更低的版本,您应该参阅默认API v1.2和更低的配置.对于版本1.3或更高版本,您可以使用“es ...
- Java中如何防止内存泄漏的发生
在Java开发中我们常常会遇到内存泄漏的情况发生.那么为什么会发生内存泄漏,以及怎样去防止! 内存泄漏的定义:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 为什么会发生 ...
- android中的selector背景选择器的用法
关于listview和button都要改变android原来控件的背景,在网上查找了一些资料不是很全,所以现在总结一下android的selector的用法. 首先android的selector是在 ...
- SQL Server数据库文件存储目录转移
USE master GO DECLARE @DBName sysname, ) DECLARE @DB table( name sysname, physical_name sysname) BEG ...
- 深入浅出百度地图API开发系列(1):前言
百度地图API目前在地图API领域越来越受到众多开发者的关注,许多应用都使用到了百度地图API服务,包括博主me,我自己使用做的是Javascript API,根据经验,我想整理出一份系列教程,如果能 ...