【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的最大 ...
随机推荐
- RHEL(RedHat Enterprise Linux)5/6 ISO镜像下载
本文贴出了RHEL(RedHat Enterprise Linux)发行版本中常用的服务器版本的ISO镜像文件,供大家下载学习使用,贴出的版本有RedHat Enterprise Linux(RHEL ...
- C# 条码标签打印程序,RDLC报表动态显示多条码标签的方法
初学c#,因最近公司客户要求原出货标签需实现条码化,练手的机会来了,遂动手做这个程序,开始都是一些增删改查操作一直很顺利,但到RDLC报表将条码显示到报表上犯难了,因为初学未接触过报表,上网查资料均一 ...
- Java基础(二)
下面来实现一个小程序,要求如下: 从键盘接收一个字符串,程序对其中所有的字符进行排序,例如键盘输入:helloitcast程序打印acehillostt 步骤分析: 1.键盘录入字符串,Scanner ...
- Optimize str2date function
The job can be any string date format convert to AX date format. so that, Do not need to specify str ...
- Spark菜鸟学习营Day4 单元测试程序的编写
Spark菜鸟学习营Day4 单元测试程序的编写 Spark相比于传统代码是比较难以调试的,单元测试的编写是非常必要的. Step0:需求分析 在测试案例编写前,需完成需求分析工作,明确程序所有的输入 ...
- 表达式语言之java对正则表达式的处理
正则表达式用于字符串匹配,字符串查找,字符串替换等.例如注册email格式的验证等.java中处理正则表达式相关的类主要有java.lang.String,java.util.regex.Patter ...
- Oracle之存储过程
1.存储过程创建 oracle中创建存储过程的语法如下: CREATE [OR REPLACE] PROCEDURE PRO_NAME[(parameter1[,parameter2]...)]is| ...
- Objective-C的内省(Introspection)小结
内省(Introspection)是面向对象语言和环境的一个强大特性,Objective-C和Cocoa在这个方面尤其的丰富.内省是对象揭示自己作为一个运行时对象的详细信息的一种能力.这些详细信息包括 ...
- php用户注册
前言 网站用户注册与登录是很常用的一个功能,本节教材就以此来演示一下 PHP 中如何开发用户注册与登录模块. 本节需要用到的重点 PHP 基础知识: PHP 中预定义 $_POST 和 $_GET 全 ...
- Ffmpeg 定位文件(seek file)
有朋友问到ffmpeg播放文件如何定位问题,我想到应该还有一些新手朋友对这一块比较陌生.ffmpeg定位问题用到seek方法,代码 如下: void SeekFrame(AVFormatContext ...