BSGS 和扩展
BSGS
BSGS,全称叫 BabyStepGiantStep,也就是大步小步
其实还是比较暴力的
它可以\(O(\sqrt p)\)的复杂度内解出:
\]
中\(x\)的值
如果\(\gcd(a,p)\neq 1\)就要用到 exBSGS 了
我们考虑令\(x=im-k,0\le k<m\)
那么原式变为
\]
\]
那么,我肯可以枚举\(k\in[0,m)\),计算出\(na^k\bmod p\)的值,然后把对应的\(k\)存下来
可以用map
或 hash,用map
会多一个\(\log\)
然后,再枚举\(i\in[0,\lceil\frac{p}{m}\rceil]\),计算出\(a^{im}\bmod p\)
然后看一看之前有没有一个\(k\),使得\(na^k\equiv a^{im}\pmod p\),且\(im>=k\)
如果有,那么答案肯定就是\(im-k\)
如果一直没找到,那么就无解
复杂度是\(O(\max(m,\frac{p}{m} ))\),显然,让\(m=\lceil \sqrt p \rceil\)时最优,即为\(O(\sqrt p)\)
但是,我们考虑的只是\(x\in[1,p]\)的情况,那为什么要找的这个\(x\)一定满足这样的性质呢?
首先\(\gcd(a,p)=1\),满足欧拉定理的条件,也就是会有\(a^{\varphi(p)}\equiv 1\pmod p\Rightarrow a^{q\varphi(p)}\equiv 1\pmod p,q\in\mathbb{N^*}\)
那么,\(k\bmod \varphi(p)=k-q\varphi(p)<\varphi(p)<p\)
则\(a^{k\bmod \varphi(p)}=\dfrac{a^k}{a^{q\varphi(p)}}\)
又由于那个分母在\(\bmod p\)中同余于\(1\)
所以\(a^{k\bmod \varphi(p)}\equiv a^k\pmod p\)
则可以得知,要求的最小的\(x\),如果有解,一定满足\(x<\varphi(p)<p\)
模板题:P3846 [TJOI2007] 可爱的质数
这题保证了\(a,n<p\),所以不需要一些奇奇怪怪的特判
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<map>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
register int x=0;register int y=1;
register char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
std::map<int,int>map;
inline int power(int a,int b,int p){
int ret=1;
while(b){
if(b&1) ret=1ll*ret*a%p;
b>>=1;a=1ll*a*a%p;
}
return ret;
}
inline int BSGS(int a,int n,int p){
reg int m=std::ceil(std::sqrt(p));
for(reg int i=0,s=n;i<m;i++,s=1ll*s*a%p) map[s]=i;
for(reg int i=0,tmp=power(a,m,p),s=1;i<=m;i++,s=1ll*s*tmp%p)
if(map.find(s)!=map.end())
if(i*m>=map[s]) return i*m-map[s];
return -1;
}
int main(){
int p=read(),a=read(),n=read();
LL ans=BSGS(a,n,p);
ans==-1?std::puts("no solution"):std::printf("%lld",ans);
return 0;
}
exBSGS
用于处理上面哪个问题\(\gcd(a,p)\neq 1\)的情况
有些细节稍显恶心(其实还好
首先,原来那个同余方程可以等价的写成:
\]
设\(\gcd(a,p)=d\)
由于斐蜀定理,这个式子有解的充要条件是\(d\mid n\),否则直接返回无解
那么上面的式子就是:
\]
此时,\(a^{x-1}\rightarrow a^x,\frac{p}{d}\rightarrow p,\frac{n}{d}\rightarrow n\)
那么一直递归,直到\(\gcd(a,p)=1\)
所以此时设一共递归了\(cnt\)次,这所有次递归的\(d\)的乘积是\(d\)(用一个字母说起来省事
原式就是
\]
那么我们就用\(a'=a,n'=\frac{n}{d},p'=\frac{p}{d}\)来跑一次 BSGS 就行了
当然,答案还要再加上\(cnt\)
而且,还有一个\(\dfrac{a^{cnt}}{d}\)的系数要乘上,具体对应代码中的变量ad
,要传参到 BSGS 的函数里
模板题:SP3105 MOD - Power Modulo Inverted,P4195 【模板】exBSGS
还是双倍经验,但是这个不保证\(a,n<p\),所以要先模一下,然后判断一下是不是等于\(0\),具体看代码
而且这个还卡常,必须要用unordered_map
,它的内部实现是哈希表,而map
是红黑树,前者构建好像稍慢,但是查询快,适合这个题
话说我写这题的时候听说卡常,然后T了以后猛卡常数,结果后来发现是写法错了,于是就对着错误的程序卡了一晚上常直至自闭
不过是 c++11 的东西,noip可能不能用,编译时要加上-std=c++11
当然写 hash 也可以,但我不太会/kk
#include<cstdio>
#include<map>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<unordered_map>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
register int x=0;register int y=1;
register char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
std::unordered_map<int,int>map;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int BSGS(int a,int n,int p,int ad){
map.clear();
reg int m=std::ceil(std::sqrt(p));
reg int s=1;
for(reg int i=0;i<m;i++,s=1ll*s*a%p) map[1ll*s*n%p]=i;
for(reg int i=0,tmp=s,s=ad;i<=m;i++,s=1ll*s*tmp%p)
if(map.find(s)!=map.end())
if(1ll*i*m-map[s]>=0) return 1ll*i*m-map[s];
return -1;
}
inline int exBSGS(int a,int n,int p){
a%=p;n%=p;
if(n==1||p==1) return 0;
reg int cnt=0;
reg int d,ad=1;
while((d=gcd(a,p))^1){
if(n%d) return -1;
cnt++;n/=d;p/=d;
ad=(1ll*ad*a/d)%p;
if(ad==n) return cnt;
}
// std::printf("a: %d n: %d p: %d ad:%d\n",a,n,p,ad);
LL ans=BSGS(a,n,p,ad);
if(ans==-1) return -1;
return ans+cnt;
}
signed main(){
int a=read(),p=read(),n=read();
while(a||p||n){
int ans=exBSGS(a,n,p);
if(~ans) std::printf("%d\n",ans);
else std::puts("No Solution");
a=read();p=read();n=read();
}
return 0;
}
BSGS 和扩展的更多相关文章
- BSGS与扩展BSGS
BSGS \(BSGS\)算法又称大步小步\((Baby-Step-Giant-Step)\)算法 \(BSGS\)算法主要用于解以下同余方程 \[A^x\equiv B(mod\ p)\]其中\(( ...
- BSGS及扩展BSGS总结(BSGS,map)
蒟蒻哪里有什么总结,只能点击%YL% 还有这位ZigZagK大佬的blog \(\mbox{BSGS}\) 模板题:洛谷P3846 [TJOI2007]可爱的质数 给定\(a,b\)和模数\(\mbo ...
- BSGS和扩展BSGS
BSGS: 求合法的\(x\)使得\(a ^ x \quad mod \quad p = b\) 先暴力预处理出\(a^0,a^1,a^2.....a^{\sqrt{p}}\) 然后把这些都存在map ...
- BSGS及其扩展
目录 定义 原理 朴素算法 数论分块 例题 Luogu2485 [SDOI2011]计算器 题解 代码 扩展 例题 Luogu4195 [模板]exBSGS/Spoj3105 Mod 代码 之前写了一 ...
- BSGS及扩展BSGS算法及例题
\(BSGS(baby-step-giant-step)\)算法是用来解高次同余方程的最小非负整数解的算法,即形如这个的方程: \(a^x\equiv b(mod\ p)\) 其中\(p\)为质数(其 ...
- Codeforces 1106F Lunar New Year and a Recursive Sequence (数学、线性代数、线性递推、数论、BSGS、扩展欧几里得算法)
哎呀大水题..我写了一个多小时..好没救啊.. 数论板子X合一? 注意: 本文中变量名称区分大小写. 题意: 给一个\(n\)阶递推序列\(f_k=\prod^{n}_{i=1} f_{k-i}b_i ...
- 数论算法 剩余系相关 学习笔记 (基础回顾,(ex)CRT,(ex)lucas,(ex)BSGS,原根与指标入门,高次剩余,Miller_Rabin+Pollard_Rho)
注:转载本文须标明出处. 原文链接https://www.cnblogs.com/zhouzhendong/p/Number-theory.html 数论算法 剩余系相关 学习笔记 (基础回顾,(ex ...
- BSGS算法学习笔记
从这里开始 离散对数和BSGS算法 扩展BSGS算法 离散对数和BSGS算法 设$x$是最小的非负整数使得$a^{x}\equiv b\ \ \ \pmod{m}$,则$x$是$b$以$a$为底的离散 ...
- Discrete Logging(POJ2417 + BSGS)
题目链接:http://poj.org/problem?id=2417 题目: 题意: 求一个最小的x满足a^x==b(mod p),p为质数. 思路: BSGS板子题,推荐一篇好的BSGS和扩展BS ...
随机推荐
- Java第二十一天,集合三大接口Set、List、Map的新方法——of方法
of public static List<E> of(E.....e) 这是jdk 9推出的一个针对于Set,List,Map三大集合接口的新方法. 注意: 是静态方法. 只适用于Set ...
- python3(十九)Partial func
# 偏函数(Partial function) # 如int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换 # 但int()函数还提供额外的base参数,默认值为10 ...
- CKEDITOR (FCKEDITOR) --- 目前最优秀的可见即可得网页编辑器之一
FCKEDITOR 编辑 同义词 CKEditor一般指FCKEDITOR FCKeditor是目前最优秀的可见即可得网页编辑器之一,它采用JavaScript编写.具备功能强大.配置容易.跨浏览器. ...
- WEB应用环境的搭建(一)配置Tomcat步骤
首先了解C/s架构 比如我们常见的QQ,魔兽世界等 这种结构的程序是有服务器来提供服务的,客户端来使用服务 而B/S架构是这样的 它不需要安装客户端,只需要浏览器就可以了 例如QQ农场,这样对客户端的 ...
- redis list 基本操作
写在前面的话 本篇笔记写在笔者刚工作时.如有问题,请指教. 简介 list是链表,redis list的应用场景很多,也是Redis 最重要的数据结构之一,比如微博的关注列表,粉丝列表,消息列表等功能 ...
- python3+selenium3自动化1——元素定位
1.selenium的webdriver提供了八种基本的元素定位方法 打开浏览器 driver = webdriver.Chrome() driver.get('https://www.baidu.c ...
- 基于Koa实现留言版demo
学习node.koa,随手做了一个留言板demo. 基本功能如下: 未登录用户可以查看主题列表和主题内容. 用户注册和登录功能. 登录用户可以发表.修改.删除自己的主题. 登录用户主题列表下方有发表主 ...
- LeetCode466. Count The Repetitions
题目链接 传送门 题意 定义一个特殊的串, 现在给出串S1和S2的参数, 问: S2最多可以多少个连接起来扔是S1的子序列, 求出这个最大值 解题思路 注意s1与S1的区别, 可以去看题目描述, 预处 ...
- 编程语言千千万,为什么学习Python的占一半?
如果让你从数百种的编程语言中选择一个入门语言?你会选择哪一个? 是应用率最高.长期霸占排行榜的常青藤 Java?是易于上手,难以精通的 C?还是在游戏和工具领域仍占主流地位的 C++?亦或是占据 Wi ...
- [Abp vNext 入坑分享] - 前言
一·背景 Abp vnext是 ABP 框架作者所发起一个完全基于 ASP .NET Core框架,截至2020年4月份已经升级到2.5.0版本,根据经验2.0版本以后可以放心的使用在生产环境.类似a ...