Baby Steps-Varsity

Giant Step-Astronauts(May'n・椎名慶治)

阅读时可以听听这两首歌,加深对这个算法的理解。(Baby steps少女时代翻唱过,这个原唱反而不是很有名……Giant Step就比较碉,是一个假面骑士片的插曲,由超碉的May'n和一个人建立的临时组合唱的,怕不怕)

这个主要是用来解决这个题:

A^x=B(mod C)(C是质数),都是整数,已知A、B、C求x。

我在网上看了好多介绍,觉得他们写得都不够碉,我看不懂…于是我也来写一发。

先把x=i*m+j,其中m=ceil(sqrt(C)),(ceil是向上取整)。

这样原式就变为A^(i*m+j)=B(mod C),

再变为A^j=B*A^(-m*i) (mod C)

先循环j=0~(C-1),把(A^j,j)加入hash表中,这个就是Baby Steps(现在可以播放Baby Steps-Varsity了)。

下面我们要做的是枚举等号右边,从hash表中找看看有没有,有的话就得到了一组i j,x=i*m+j,得到的这个就是正确解。

所以,接下来要解决的就是枚举B*A^(-m*i) (mod C)这一步(这就是Giant Step,快放Giant Step-Astronauts(May'n・椎名慶治))。

A^(-m*i)相当于1/(A^(m*i)),里面有除法,在mod里不能直接用除法,这时候我们就要求逆元

/*百度百科:

若ax≡1 mod f, 则称a关于模f的乘法逆元为x。也可表示为ax≡1(mod f)。
当a与f互素时,a关于模f的乘法逆元有唯一解。如果不互素,则无解。如果f为素数,则从1到f-1的任意数都与f互素,即在1到f-1之间都恰好有一个关于模f的乘法逆元。
*/
 
然后我们用超碉的exgcd求逆元,exgcd(扩展欧几里德算法)就是在求AB的最大公约数z的同时,求出整数x和y,使xA+yB=z。算法实现就是gcd加几个语句。
然后我们再来看一下exgcd怎么求逆元:

对xA+yB=z,

变成这样xA = z - yB,取B=C(C就是我们要mod的那个)

推导出 xA % C = z %C

只要  z%C==1 时,就可以求出A的逆元x

但用exgcd求完,x可能是负数,还需要这样一下:x=(x%C+C)%C

//--exgcd介绍完毕--

再看我们的题目,

exgcd(A^(m*i) , C)=z,当C是质数的时候z肯定为1,这样exgcd求得的x就是逆元了。

因为x就是A^(m*i)的逆元,P/(A^(m*i))=P*x,所以

B*A^(-m*i) = B/(A^(m*i)) = B*x(mod C)

这样我们的式子A^j=B*A^(-m*i) (mod C)的等号右边就有了,就是B*x,就问你怕不怕!

枚举i,求出右边在hash里找,找到了就返回,无敌!

例题:

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

代码:

 #include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
using namespace std;
#define ll __int64
#define usint unsigned int
#define RE freopen("1.in","r",stdin) class hash {
public:
hash() {
memset(a,0xff,sizeof(a));
}
int locate(ll x) {
ll l=x%MOD;
while(a[l]!=x&&a[l]!=-) l=(l+)%MOD;
return l;
}
void insert(ll x,ll va) {
ll l=locate(x);
if(a[l]==-) {
a[l]=x;
v[l]=va;
}
}
ll get(ll x) {
ll l=locate(x);
return a[l]==x?v[l]:-;
}
void clear() {
memset(a,0xff,sizeof(a));
}
private:
static const ll MOD=;
ll a[MOD+],v[MOD+];
} S; ll exgcd(ll a,ll b,ll &x,ll &y) {
ll t,ret;
if (!b) {
x=,y=;
return a;
}
ret=exgcd(b,a%b,x,y);
t=x,x=y,y=t-a/b*y;
return ret;
} int main() {///A^x=B(modC) A^j=B*A^(-m*i)(mod C)
ll C,A,B;
ll m,i,t,D,ans,x,y;
while(scanf("%lld%lld%lld",&C,&A,&B)!=EOF) {
S.clear();
m=ceil(sqrt((double)C));
t=;
for(i=; i<m; i++) { /**One, two, baby steps.Three, four, baby steps.Five, six, baby steps.**/
S.insert(t,i);
t=t*A%C;
}
D=;///此时t=A^m
ans=-;
for(i=; i<m; i++) { /**一歩 Giant Step , 君にとってLittle だとしても**/
exgcd(D,C,x,y);///exgcd求逆元,得到x=D^(-i*m)
x=((x*B)%C+C)%C;///B*x=B*D^(-i*m)
y=S.get(x);
//printf("%lld,%lld\n",x,y);
if(y!=-) {
ans=i*m+y;
break;
}
D=(D*t)%C;///D=t^i,(t=A^m)
}
if(ans==-) printf("no solution\n");
else printf("%lld\n",ans);
}
return ;
}

BSGS算法_Baby steps giant steps算法(无扩展)详解的更多相关文章

  1. BSGS(Baby Steps,Giant Steps)算法详解

    BSGS(Baby Steps,Giant Steps)算法详解 简介: 此算法用于求解 Ax≡B(mod C): 由费马小定理可知: x可以在O(C)的时间内求解:  在x=c之后又会循环: 而BS ...

  2. bsgs(Baby Steps Giant Steps)算法

    BSGS算法(Baby Steps Giant Steps算法,大步小步算法,北上广深算法,拔山盖世算法) 适用问题 对于式子: $$x^y=z(mod_p)$$ 已知x,z,p,p为质数: 求解一个 ...

  3. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  4. BSGS_Baby steps giant steps算法

    BSGS这个主要是用来解决这个题: A^x=B(mod C)(C是质数),都是整数,已知A.B.C求x. 在具体的题目中,C一般是所有可能事件的总数. 解: 设m = ceil(sqrt(C))(ce ...

  5. NOI / 2.5基本算法之搜索-6044:鸣人和佐助详解

    总时间限制: 1000ms 内存限制: 65536kB 题目 佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢? 已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置.地图上的每个位置都可以走到, ...

  6. 二分算法题目训练(三)——Anton and Making Potions详解

    codeforces734C——Anton and Making Potions详解 Anton and Making Potions 题目描述(google翻译) 安东正在玩一个非常有趣的电脑游戏, ...

  7. DOM对象控制HTML无素——详解3

    创建元素节点createElement createElement()方法可创建元素节点.此方法可返回一个 Element 对象. 语法: document.createElement(tagName ...

  8. DOM对象控制HTML无素——详解2

    节点属性 在文档对象模型 (DOM) 中,每个节点都是一个对象.DOM 节点有三个重要的属性 : 1. nodeName : 节点的名称 2. nodeValue :节点的值 3. nodeType ...

  9. DOM对象控制HTML无素——详解1

    getElementsByName()方法 返回带有指定名称的节点对象的集合. 语法: document.getElementsByName(name) 与getElementById() 方法不同的 ...

随机推荐

  1. linux内核分析 第八周

    第八周 理解进程调度时机跟踪分析进程调度与进程切换的过程 一.进程调度与切换 1.进程的调度时机与进程切换 操作系统原理中介绍了大量进程调度算法,这些算法从实现的角度看仅仅是从运行队列中选择一个新进程 ...

  2. 自己写的一个关于Linq to Entity 动态查询的例子

    这两天一直想写一个动态查询的方式,先是晚上查询了一下,发现大家写的差不多都是一样的[如:http://www.cnblogs.com/ASPNET2008/archive/2012/10/28/274 ...

  3. 大数据:从开源告诉你身边的IT故事

    最近我们Team利用Dream分布式计算平台,做了这样一件事情,将Github的大量数据通过爬虫抓取下来,通过分析后,我们抽取最近一年中部分的开发者和项目信息,得到了如下有趣的信息,故分享之,数据原汁 ...

  4. webstorm调试Node的时候配置

    点击Edit Configurations的这个的配置:(不能点击是因为目前你选中的不是项目)

  5. Grovvy初识

    1.Groovy和Java对比 Groovy的松散的语法允许省略分号和修饰符 除非另行指定,Grovvy的所有内容都为public Grovvy允许定义简单脚本,同时无需定义正规的class对象 Gr ...

  6. 配置ipvsadm服务

    LVS的三种包转发方式      LVS提供了三种包转发方式:NAT(网络地址映射).IP Tunneling(IP隧道).Direct Routing(直接路由)     不同的转发模式决定了不同的 ...

  7. 在Myeclipse buildpath 加server lib (server runtime)/项目导入时报错:The import javax.servlet.http.HttpServletRequest cannot be resolved

    来源于:http://blog.csdn.net/dingqinghu/article/details/8805922 http://yl-fighting.iteye.com/blog/140946 ...

  8. zabbix修改密码

    在我们刚刚安装好zabbix之后我们的管理用户是 Admin,密码是zabbix 所以我们肯定是要更改密码的,这个方法也适用于我们忘记管理员密码 首先我们登录mysql数据库 这里有一个zabbix库 ...

  9. Jquery-获取同级标签prev,prevAll,next,nextAll

    1.next([expr]): 获取指定元素的下一个同级元素(注意是下一个同级元素哦) 参数可有可无,参数设定遵循jquery选择器规则 <!DOCTYPE html> <html& ...

  10. POJ3233 Matrix Power Series

    Description Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak. ...