【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的最大 ...
随机推荐
- 《samba服务配置的文本》
创建简单的samba服务器 samba 很少用于互联网 /大部分用于局域网 网页更新/ 首先看下你是否安装后了samba. rpm -qa | grep samba samba的简介 1)samb ...
- canvas 绘点图
canvas 绘点图 项目中需要一个记录点实时变动的信息,在此记录一下: <!DOCTYPE html> <html lang="en"> <head ...
- 腾讯微博OAuth2.0 .NET4.0 SDK 发布以及网站腾讯微博登陆示例代码(原创)
1.使用简单方便,包含详细注释: 2.暂时只支持xml格式字符串的转换,建议接口使用xml参数:3.QweiboSDK.Controllers命名空间下已包含所有API接口:4.只需调用到Qweibo ...
- centos问题集锦
一. 为什么新装的centos系统无法使用xshell,putty等工具连接? 原因:sshd服务没有启动. 解决: 1)使用命令rpm -qa | grep ssh查看是否已经安装了ssh 2)使用 ...
- 为ProgressBar进度条设置颜色1
可以通过xml文件来设置,方法如下: 1:先在布局文件中的ProgressBar加入下面属性: android:progressDrawable="@drawable/progress_ba ...
- 使用VisualSVN Server自动发布站点
使用VisualSVN Server自动发布站点可以节省大量的发布时间. 适用于项目测试版本 通常一个项目在测试阶段会遇到以下问题 1.开发人员修改缺陷要实时反应到测试环境 2.项目经理想让客户及时看 ...
- Qt在VS2010的安装与配置
1. 下载Qt的安装包和VS2010的Qt插件 2. 安装Qt SDK 点击下载安装包,一路回车即可,主要注意Qt的安装路径最好安装在全英文路径而且中间没有空格, 安装好后,可以运行开始菜单里面的Qt ...
- WPF编译时提示“...不包含适合于入口点的静态‘Main’方法 ...”
今天看了一下wpf的Application类方面的知识,一个windows应用程序由一个Application类的实例表示,该类跟踪在应用程序中打开的所有窗口,决定何时关闭应用程序(属性 Shutdo ...
- HDU 1465 第六周L题
Description 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了! 做好“一件”事情尚且不易,若想永远成功而总从不失败,那更是难上加难了,就像花钱总是比挣钱容易的道理一样. ...
- Unity 优化
1. 尽量避免每帧处理比如: function Update() { DoSomeThing(); } 可改为每5帧处理一次: function Update() { == ) { DoSomeThi ...