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. Opencv Linux环境搭建(2)

    继上次ubuntu10.04搭建失败之后,这次又换了一个系统. 拿出之前闲置的笔记本,安装了ubuntu12.04,按照这里的教程开始搞起来: http://www.linuxidc.com/Linu ...

  2. css优化篇

    平时总说如何如何优化,今天就详细的写一下css如何优化,嘿嘿. 首先,CSS的优化工作主要从两个方面着手 网络性能:把CSS写到字节数最少,加快下载速度,自然可以让页面渲染的更快一些 语法性能:同样都 ...

  3. 回顾一年的IT学习历程与大学生活

    今天是2015年8月27日,距离成为大三狗还有一个多星期,在这个不算繁忙的暑假的下午来总结一下这一年来,在IT方面的学习. 一.入门(2014.3) 我大一的专业是信息工程,信息工程听上去就是信息(I ...

  4. 关于页面滚动值scrollTop在FireFox与Chrome浏览器间的兼容问题

    需求 最近在做博客的目录功能,发现一个在现代浏览器间的一个bug,或是称之为差异,即页面滚动值(scrollTop)的获取与设定. 在此之前先说一下关于页面元素的坐标获取,这张图的经典性不必再提. 实 ...

  5. [C/C++基础] C语言常用函数strlen的使用方法

    函数声明:extern unsigned int strlen(char *s); 所属函数库:<string.h> 功能:返回s所指的字符串的长度,其中字符串必须以’\0’结尾 参数:s ...

  6. $().each() 与 $.each()解析

    在jquery 中我们可以选择$().each() 与 $.each() 进行迭代对象和数组 $(items).each(function(){ //item }) , 而后者则 $.each(ite ...

  7. C#中值类型和引用类型

    本文将介绍C#类型系统中的值类型和引用类型,以及两者之间的一些区别.同时,还会介绍一下装箱和拆箱操作. 值类型和引用类型 首先,我们看看在C#中哪些类型是值类型,哪些类型是引用类型. 值类型: 基础数 ...

  8. Mysql 调优小技巧

    MySQL是一个功能强大的开源数据库.随着越来越多的数据库驱动的应用程序,人们一直在推动MySQL发展到它的极限.这里是101条调节和优化MySQL安装的技巧.一些技巧是针对特定的安装环境的,但这些思 ...

  9. upstream 负载均衡

    首先拿一个实例来进行记录 upstream webyz {        ip_hash;        server 10.23.24.10:8026 weight=1 max_fails=2 fa ...

  10. Quartz 定时任务管理

    前言 将项目中的所有定时任务都统一管理吧,使用 quartz 定时任务 设计思路 使用 quartz 的相关jar 包,懒得去升级了,我使用的是 quart 1.6 写一个定时任务管理类 用一张数据库 ...