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. Java系列:Add Microsoft SQL JDBC driver to Maven

    Maven does not directly support some libraries, like Microsoft's SQL Server JDBC. This tutorial will ...

  2. [MySQL] 按日期进行统计(前一天、本周、某一天)

    在mysql数据库中,常常会遇到统计当天的内容.例如,在user表中,日期字段为:log_time统计当天 sql语句为: select * from user where date(log_time ...

  3. js浮点数精确计算(加、减、乘、除)

    <SPAN style="FONT-SIZE: 18px">//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显.这个函数返回较为精确的加 ...

  4. 20145215《Java程序设计》第8周学习总结

    20145215<Java程序设计>第八周学习总结 教材学习内容总结 NIO与NIO2 认识NIO NIO使用频道(Channel)来衔接数据节点,在处理数据时,NIO可以设定缓冲区(Bu ...

  5. (转)shell实例手册

    原文地址:http://hi.baidu.com/quanzhou722/item/f4a4f3c9eb37f02d46d5c0d9 实在是太好的资料了,不得不转 shell实例手册 0说明{ 手册制 ...

  6. 如何构建JSON数据,JSON数据的格式,JSON数据的获取

    假设你是用$.getJSON();方法获取JSON数据$.getJSON(url,{"Action":"getStudent"},function(data){ ...

  7. html5 canvas 粒子特效

    不知不觉就已经好久没写过博客了,自从七月正式毕业后,离开了实习了将近九个月的老东家,进了鼠厂后,做的事都是比较传统的前端活,之前在tpy的时候只管做移动h5的特效以及小游戏,再加上实习所以时间比较充裕 ...

  8. webstorm调试Node的时候配置

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

  9. loadsh这个神奇的js工具类库

    var _ = require('lodash'); 把几个对象合并为一个对象. _.assign({ 'a': 1 }, { 'b': 2 }, { 'c': 3 });// ➜ { 'a': 1, ...

  10. AngularJS开发指南1:AngularJS简介

    什么是 AngularJS? AngularJS 是一个为动态WEB应用设计的结构框架.它能让你使用HTML作为模板语言,通过扩展HTML的语法,让你能更清楚.简洁地构建你的应用组件.它的创新点在于, ...