BSGS与扩展BSGS
BSGS
\(BSGS\)算法又称大步小步\((Baby-Step-Giant-Step)\)算法
\(BSGS\)算法主要用于解以下同余方程
\]
其中\((A,P)=1\),即\(A\)与\(P\)互质
前置知识
根据欧拉定理\(A^{ \varphi(p)} \equiv1(mod\ p)\),所以\(A^x(mod\ p)\)的循环节为\(\varphi(p)\).也就是说如果上面的方程有解\(x\),那么肯定有\(x \in [0,\varphi(p)]\),所以我们可以枚举一下\(x\)求解
推导
上面是暴力的做法,而\(BSGS\)就是利用分块的思想将上面的算法复杂度优化为\(\sqrt{\varphi(p)}\)(哈希表做法)或者\(\sqrt{\varphi(p)}\ log\;p\)(map)做法
我们令\(m=\lceil \sqrt{\varphi(p)}\rceil\),那么任何一个\(x\in [0,\varphi(p)]\)都可以被表示成\(im-j(i \in [1,m],j\in [0,m])\)的形式
则原式可表示为$$A^{im-j} \equiv B(mod\ p)$$
\]
实现
所以先将右边\(A^jB(j \in[0,m])\)预处理出来,存到\(hash\)表中。
然后枚举左边的\(i \in[1,m]\)计算出\(A^{im}\),并在\(hash\)表中查询。
枚举\(i,j\)的复杂度都是\(\sqrt{\varphi(p)}\),常数取决于\(hash\)表
有个细节的地方,一般我们都是要求\(x\)最小的,所以我们希望\(j\)更大,\(i\)更小。所以在往\(hash\)表中存的时候,保留更大的那个\(j\)。从小到大枚举\(i\),遇到可行答案直接输出即可。
例题
代码
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<map>
using namespace std;
typedef long long ll;
#define int ll
map<int,int>ma;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int B,A,L,P;
int qm(int x,int y) {
int ret = 1;
for(;y;y >>= 1,x = 1ll * x * x % P)
if(y & 1) ret = 1ll * x * ret % P;
return ret;
}
signed main() {
P = read(),A = read(),B = read();
ma.clear();
int m = ceil(sqrt(P));
int now = B;
for(int i = 0;i <= m;++i) {
ma[now] = i + 1;
now = 1ll * now * A % P;
}
now = 1;
int ans = -1;
int kk = qm(A,m);
for(int i = 1;i <= m;++i) {
now = 1ll * now * kk % P;
if(ma[now]) {
ans =i * m - ma[now] + 1;
break;
}
}
if(ans == -1) puts("no solution");
else printf("%lld\n",ans);
return 0;
}
扩展BSGS
\(BSGS\)算法有一定的局限性\((A,p\)互质\()\)。扩展\(BSGS\)可以处理\(A,p\)不互质的情况。
推导
我们已经会了\(A,p\)互质的情况,对于\(A,p\)不互质的情况,只要将转化为\(A,p\)互质即可。
令\(d=gcd(A,p)\)。
如果\(d\nmid B\),那么要么\(B=1\),则答案为\(0\)。否则根据裴蜀定理一定无解。所以我们只要在一开始的时候特判一下\(B=1\)的情况。后面只要发现\(d\nmid B\)就可以说明无解。
所以现在我们假设\(d\mid B\)。
我们将\(A,B,P\)同时除以一个\(d\)。即
\]
然后重复此操作,直到\(d = 1\)
得到同余方程
\]
设\(p'=\frac{p}{\prod\limits_{i=1}^kd_i},B'=\frac{B}{\prod\limits_{i=1}^kd_i},C=\frac{A^k}{\prod\limits_{i=1}^kd_i},x'=x-k\)
原式就变为$$A^{x'}C\equiv B'(mod\ p')$$
然后就转化为了\(A,p'\)互质的情况,就可以用普通的\(BSGS\)做了。
例题
代码
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<map>
using namespace std;
typedef long long ll;
#define int ll
map<int,int>ma;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int A,B,P;
int gcd(int x,int y) {
return !y ? x : gcd(y,x % y);
}
int qm(int x,int y) {
int ans = 1;
for(;y;y >>= 1,x = 1ll * x * x % P) {
if(y & 1) ans = 1ll * ans * x % P;
}
return ans;
}
signed main() {
// freopen("in.in","r",stdin);
while(1) {
ma.clear();
A = read(),P = read(),B = read();
if(!A and !B and !P) return 0;
if(B == 1) {
puts("0");continue;//特判掉b=1的情况
}
int bz = 0,C = 1,d = gcd(A,P),K = 0;
while(d != 1) {
if(B % d) {
puts("No Solution");
bz = 1;break;
}
P /= d;
B /= d;
++K;
C = 1ll * C * (A / d) % P;
d = gcd(A,P);
if(B == C) {
printf("%d\n",K);
bz = 1;
break;
}
}
if(bz == 1) continue;
int m = ceil(sqrt(P));
int now = B;
for(int i = 0;i <= m;++i) {
ma[now] = i + 1;
now = 1ll * now * A % P;
}
now = C;
int ans = -1;
int kk = qm(A,m);
for(int i = 1;i <= m;++i) {
now = 1ll * now * kk % P;
if(ma[now]) {
ans =i * m - ma[now] + 1 + K;
break;
}
}
if(ans == -1) puts("No Solution");
else printf("%lld\n",ans);
}
return 0;
}
BSGS与扩展BSGS的更多相关文章
- BSGS和扩展BSGS
BSGS: 求合法的\(x\)使得\(a ^ x \quad mod \quad p = b\) 先暴力预处理出\(a^0,a^1,a^2.....a^{\sqrt{p}}\) 然后把这些都存在map ...
- BSGS及扩展BSGS总结(BSGS,map)
蒟蒻哪里有什么总结,只能点击%YL% 还有这位ZigZagK大佬的blog \(\mbox{BSGS}\) 模板题:洛谷P3846 [TJOI2007]可爱的质数 给定\(a,b\)和模数\(\mbo ...
- BSGS及扩展BSGS算法及例题
\(BSGS(baby-step-giant-step)\)算法是用来解高次同余方程的最小非负整数解的算法,即形如这个的方程: \(a^x\equiv b(mod\ p)\) 其中\(p\)为质数(其 ...
- BSGS&扩展BSGS
BSGS 给定\(a,b,p\),求\(x\)使得\(a^x\equiv b \pmod p\),或者说明不存在\(x\) 只能求\(\gcd(a,p)=1\)的情况 有一个结论:如果有解则必然存在\ ...
- POJ 3243 Clever Y 扩展BSGS
http://poj.org/problem?id=3243 这道题的输入数据输入后需要将a和b都%p https://blog.csdn.net/zzkksunboy/article/details ...
- bzoj 3283 扩展BSGS + 快速阶乘
T2 扩展BSGS T3 快速阶乘 给定整数n,质数p和正整数c,求整数s和b,满足n! / pb = s mod pc 考虑每次取出floor(n/p)个p因子,然后将问题转化为子问题. /*** ...
- poj 3243 Clever Y && 1467: Pku3243 clever Y【扩展BSGS】
扩展BSGS的板子 对于gcd(a,p)>1的情况 即扩展BSGS 把式子变成等式的形式: \( a^x+yp=b \) 设 \( g=gcd(a,p) \) 那么两边同时除以g就会变成: \( ...
- 扩展BSGS求解离散对数问题
扩展BSGS用于求解axΞb mod(n) 同余方程中gcd(a,n)≠1的情况 基本思路,将原方程转化为a与n互质的情况后再套用普通的BSGS求解即可 const int maxint=((1< ...
- BSGS及其扩展
目录 定义 原理 朴素算法 数论分块 例题 Luogu2485 [SDOI2011]计算器 题解 代码 扩展 例题 Luogu4195 [模板]exBSGS/Spoj3105 Mod 代码 之前写了一 ...
随机推荐
- webpack安装、基本配置
文章结构: 什么是webpack? 安装webpack webpack基本配置 一.什么是webpack? 在学习react时发现大部分文章都是react和webpack结合使用的,所以在学react ...
- hadoop1.0 和 Hadoop 2.0 的区别
1.Hadoop概述 在Google三篇大数据论文发表之后,Cloudera公司在这几篇论文的基础上,开发出了现在的Hadoop.但Hadoop开发出来也并非一帆风顺的,Hadoop1.0版本有诸多局 ...
- t-sql语句创建表(基础)
create table ta1 ( id int identity(1,2) not null, name nvarchar(20) not null, identify v ...
- ServiceStack.Redis连接阿里云redis服务时使用连接池出现的问题
创建连接池 private static PooledRedisClientManager prcm = CreateManager(new string[] { "password@ip: ...
- 目录命令(dir)
DIR 命令: // 描述: (Directory) 显示目录的文件和子目录的列表. // 语法: dir [<Drive>:][<Path>][<FileName> ...
- VMware实现iptables NAT及端口映射
1. 前言 本文只讲解实战应用,不会涉及原理讲解.如果想要了解iptables的工作流程或原理可参考如下博文. 具体操作是在PC机的VMware虚拟机上进行的,因此涉及的地址都是内网IP.在实际工作中 ...
- 云数据库PolarDB(一)
一.出现的背景及PolarDB简介 阿里云,中国第一家拥有完整云计算能力的企业. 2015年,在计算界的奥运会Sort Benchmark中,阿里云计算100TB数据排序只用了不到7分钟,把Apach ...
- Python爬虫【解析库之beautifulsoup】
解析库的安装 pip3 install beautifulsoup4 初始化 BeautifulSoup(str,"解析库") from bs4 import BeautifulS ...
- Java 通过地址获取经纬度 - 高德地图
一.添加依赖 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-v ...
- ansible 与 Jinja2的结合
1.文件架构 [root@master template]# tree . ├── jinj2_test.yml ├── meta ├── tasks ├── templates │ └── te ...