BSGS

引入

求解关于\(X\)的方程,

\[A^X\equiv B \pmod P
\]

其中\(Gcd(A,P)=1\)

求解

我们令\(X=i*\sqrt{P}-j\),其中\(0<=i,j<=\sqrt{P}\)

则原式可以变为:

\[A^X\equiv B \pmod P
\]
\[A^{i*\sqrt{P}-j}\equiv B \pmod P
\]

由于\(Gcd(A,P)=1\),则可以恒等变化为:

\[A^{i*\sqrt{P}}\equiv B*A^j \pmod P
\]

则我们可以先预处理出所有的\(A^{i*\sqrt{P}}\),存入哈希表。

再枚举\(B*A^j\),在哈希表里查找即可得解。

代码

int quick_Pow(int x,int y,int p){
if(y==0)return 1;
if(y==1)return x;
if(y%2)return 1ll*x*quick_Pow(1ll*x*x%p,y/2,p)%p;
return quick_Pow(1ll*x*x%p,y/2,p);
}
void BSGS(int x,int y,int p){
x%=p;y%=p;
if(x==0&&y!=0){puts("-1");return ;}
if(x==0&&y==0){puts("1");return ;}
if(y==1){puts("0");return ;}
int st=int(sqrt(p))+1;Mp.clear();
for(int i=1,rt=1;i<=st;i++,rt=(1ll*rt*x)%p)Mp[rt]=i;
int sum=quick_Pow(x,st,p);
for(int i=1,rt=1;i<=st;i++){
rt=(1ll*rt*sum)%p;
if(Mp[rt]){
printf("%d\n",i*st-Mp[rt]);
return ;
}
}
puts("-1");
}

ExBSGS

引入

求解关于\(X\)的方程,

\[A^X\equiv B \pmod P
\]

其中\(Gcd(A,P)\)无特殊条件。

由于\(Gcd(A,P)\)可能不为\(1\),所以\(A\)关于\(P\)可能没有逆元。

故不能用一般的 BSGS 求解。

求解

我们设\(D=Gcd(A,P)\),

则显然有 \(\frac{A}{D}\equiv 1\pmod P\)

则原式$$A^X\equiv B \pmod P$$

可恒等变形为$$A^{X-1}\cdot\frac{A}{D}\equiv \frac{B}{D} \pmod {\frac{P}{D}}$$

而由于\(Gcd(\frac{A}{D},\frac{P}{D})=1\),则有

\[A^{X-1}\equiv \frac{B}{D}\cdot({\frac{A}{D}})^{-1} \pmod {\frac{P}{D}}
\]

则此时\(\frac{P}{D}\)就相当于新的\(P\)值,\(\frac{B}{D}\cdot({\frac{A}{D}})^{-1}\)就相当于新的\(B\)值,

就可以这样递推下去了。(注:下一次的\(D\)是新的\(P\)值与\(A\)的\(Gcd\))

考虑边界状态:

①:若当前的\(D=1\),则问题转化为普通的 BSGS。

②:若\(B\)值等于\(1\)了,则迭代到的\(Ans\)值为\(1\)。

③:若\(D \nmid B\),即\(D\)不是\(B\)的因数,则\(\frac{B}{D}\)没有意义,则无解。

综上,出解。

例题及代码

板题

题意:求满足\(A^X\equiv B \pmod{P}\)的最小整数\(X\)

#include<map>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<tr1/unordered_map>
using namespace std;
#define LL long long
tr1::unordered_map<LL,int>Mp;
LL Gcd(LL x,LL y){
if(x==0)return y;
return Gcd(y%x,x);
}
LL quick_Pow(LL x,LL y,LL p){
if(y==0)return 1;
if(y==1)return x;
if(y%2)return x*quick_Pow(x*x%p,y/2,p)%p;
return quick_Pow(x*x%p,y/2,p);
}
int ExBSGS(int x,int y,int p){
if(y==1)return 0;//特判解为0的情况.
LL k=0,a=1;
while(1){
int d=Gcd(x,p);if(d==1)break;
if(y%d)return -1;
y/=d;p/=d;k++;a=(1ll*a*x/d)%p;
if(a==y)return k;//同特判.
}Mp.clear();
LL st=int(sqrt(p))+1,sum=quick_Pow(x,st,p);
for(LL i=0,rt=y;i<=st;i++,rt=(1ll*rt*x)%p)Mp[rt]=i+1;
for(LL i=1,rt=(a*sum)%p;i<=st;i++,rt=(1ll*rt*sum)%p){//不将求解中的A/D移项.
if(!Mp[rt])continue;
return 1ll*i*st-(Mp[rt]-1)+k;
}
return -1;
}
int A,B,C;
int main(){
while(~scanf("%d%d%d",&A,&B,&C)&&A){
int Ans=ExBSGS(A,C,B);
if(Ans!=-1)printf("%d\n",Ans);
else puts("Orz,I can’t find D!");
}
}

注:一般的,题目所给的A,B,C都是正整数。

关于 BSGS 以及 ExBSGS 算法的理解的更多相关文章

  1. openCV中直方图均衡化算法的理解

    直方图均衡化就是调整灰度直方图的分布,即将原图中的灰度值映射为一个新的值.映射的结果直观表现是灰度图的分布变得均匀,从0到255都有分布,不像原图那样集中.图像上的表现就是对比度变大,亮的更亮,暗的更 ...

  2. SDUT OJ 数据结构实验之串一:KMP简单应用 && 浅谈对看毛片算法的理解

    数据结构实验之串一:KMP简单应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...

  3. POJ1523(割点所确定的连用分量数目,tarjan算法原理理解)

    SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7406   Accepted: 3363 Description C ...

  4. 【转】浅谈对主成分分析(PCA)算法的理解

    以前对PCA算法有过一段时间的研究,但没整理成文章,最近项目又打算用到PCA算法,故趁热打铁整理下PCA算法的知识.本文观点旨在抛砖引玉,不是权威,更不能尽信,只是本人的一点体会. 主成分分析(PCA ...

  5. Vue中diff算法的理解

    Vue中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DOM结 ...

  6. 关于KMP算法中,获取next数组算法的理解

    参考:KMP入门级别算法详解--终于解决了(next数组详解) https://blog.csdn.net/lee18254290736/article/details/77278769 在这里讨论的 ...

  7. React中diff算法的理解

    React中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DO ...

  8. 知识点简单总结——BSGS与EXBSGS

    知识点简单总结--BSGS与EXBSGS BSGS 给出 $ A,B,C,(A,C)=1 $ ,要你求最小的 $ x $ ,使得 $ A^x \equiv B(mod \ C) $ . 在数论题中经常 ...

  9. 自己对kmp算法的理解,借由 28. 实现 strStr() 为例

    做题思路 or 感想 : 就借由这道题来理解一下kmp算法吧 kmp算法的操作过程我觉得有句话很合适 :KMP 算法永不回退 目标字符串 的指针 i,不走回头路(不会重复扫描 目标字符串),而是借助 ...

随机推荐

  1. Java|从Integer和int的区别认识包装类

    https://blog.csdn.net/darlingwood2013/article/details/96969339?utm_medium=distribute.pc_relevant.non ...

  2. css画叉叉(一般用于关闭按钮)

    css 一般用于右上角关闭弹窗 #pdclose { width: 18px; height: 18px; cursor: pointer; float: right; position: relat ...

  3. c#多进程通讯,今天,它来了

    引言 在c#中,可能大多数人针对于多线程之间的通讯,是熟能生巧,对于AsyncLocal 和ThreadLocal以及各个静态类中支持线程之间传递的GetData和SetData方法都是信手拈来,那多 ...

  4. stm32单片机利用ntc热敏电阻温度转换公式C语言版

    首先 我们需要明确电路结构 热敏电阻的原理就不再赘述,本文不凑字数,只讲干货 必须要知道的就是串联电阻R9程序中定义为resistanceInSeries ,精度越高越好 为了方便,先在程序中定义好你 ...

  5. Redis介绍一

    一.五中数据类型 String: 字符串 Hash: 散列 List: 列表 Set: 集合 Sorted Set: 有序集合 Redis 发布订阅 Redis 发布订阅 (pub/sub) 是一种消 ...

  6. Spring系列1:Spring基本概念

    本文内容 什么是Spring? 为什么学Spring? 本系列包含哪些技术? 本系列适合哪些人? 什么是Spring? 基本概念 Spring 框架为现代基于 Java 的企业应用程序提供了一个全面的 ...

  7. 安装MySQL到Ubuntu 20.04

    本文的内容主要来自对How To Install MySQL on Ubuntu 20.04的翻译.在根据该文的指导下,我在自己的Ubuntu 20.04.3 LTS版本中安装了MySQL 8. St ...

  8. JQuery选择器的使用和分类

    jQuery选择器 id选择器格式 $("#box") //获取标签里的id是box的标签 类选择器格式 $(".a") //获取标签里的类名是a的标签 标签选 ...

  9. DEEP LEARNING WITH PYTORCH: A 60 MINUTE BLITZ | TENSORS

    Tensor是一种特殊的数据结构,非常类似于数组和矩阵.在PyTorch中,我们使用tensor编码模型的输入和输出,以及模型的参数. Tensor类似于Numpy的数组,除了tensor可以在GPU ...

  10. zip压缩,解压

    //引用 System.IO.Compression.FileSystem.dll var basePath = AppDomain.CurrentDomain.BaseDirectory; Syst ...