『高次同余方程 Baby Step Giant Step算法』
<更新提示>
<第一次更新>
<正文>
高次同余方程
一般来说,高次同余方程分\(a^x \equiv b(mod\ p)\)和\(x^a \equiv b(mod\ p)\)两种,其中后者的难度较大,本片博客仅将介绍第一类方程的解决方法。
给定\(a,b,p\),其中\(gcd(a,p)=1\),求方程\(a^x \equiv b(mod\ p)\)的最小非负整数解。
普通分析和朴素算法
先介绍一下欧拉定理:
如果正整数\(a\),\(p\)互质,则\(a^{\phi(p)}\equiv1(mod\ p)\)。
注意到题中所给的条件符合欧拉定理的前提条件,所以我们得知\(a^{\phi(p)}\equiv 1(mod\ p)\),又因为\(\phi(p)\leq p-1\),\(a^0\equiv 1(mod\ p)\),所以在\(0\)到\(p-1\)范围内,模\(p\)意义下\(a\)的幂一定形成了至少一次循环。也就是说,我们只要在\(0\)到\(p-2\)范围内枚举解\(x\),就一定能找到解,用快速幂判断即可求解该方程,时间复杂度\(O(plog_2p)\)。
Baby Step Giant Step算法
对于求解该类高次同余方程,\(Baby\ Step\ Giant\ Step\)可以优化枚举算法,在\(O(\sqrt p)\)的时间内求解该方程。
我们设解\(x=i*t-j\),其中\(0\leq j \leq t-1\),则方程为\(a^{i*t+j}\equiv b(mod\ p)⇔(a^t)^i\equiv b*a^j(mod\ q)\)。
对于所有的\(j\in[0,t-1]\),将\(b*a^j\ mod\ p\)的值插入\(hash\)表。
枚举\(i\)的所有可能取值\([0,\frac{p}{t}]\),计算出\((a^t)^i\ mod\ p\)的值,并在\(hash\)表中检索该值,如果该值存在,就可以用\(i*t-j\)更新答案。
该算法可以保证枚举到\(x\)在\([0,p-2]\)范围内的每一种情况,其时间复杂度为\(O(\frac{p}{t}+p)\),该函数为经典的对勾函数,当参数\(t\)取\(\sqrt p\)时,其函数值最小,保证其时间复杂度为\(O(\sqrt p)\)。
以下给出求解方程最小非负整数解的程序,无解时返回\(-1\)。
\(Code:\)
inline long long Baby_Step_Giant_Step(long long a,long long b,long long p)
{
map < long long , long long > hash;hash.clear();
b%=p;long long t=(long long)sqrt(p)+1,mul=1;
for (int j=0;j<t;j++)
{
hash[ mul * b % p ] = j;
mul = mul * a % p;
}
if (a%p==0)return b==0 ? 1 : -1;
a = 1;
for (int i=0;i<=t;i++)
{
long long j = ( hash.find(a) != hash.end() ? hash[a] : -1 );
if (j>=0&&i*t-j>=0)return i*t-j;
a = a * mul % p;
}
return -1;
}
计算器
Description
你被要求设计一个计算器完成以下三项任务:
1、给定y,z,p,计算Y^Z Mod P 的值;
2、给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数;
3、给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数。
Input Format
输入包含多组数据。
第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下行每行包含三个正整数y,z,p,描述一个询问。
Output Format
对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。
Sample Input
3 1
2 1 3
2 2 3
2 3 3
Sample Output
2
1
2
解析
同余方程模板题。对于询问\(1\),快速幂解决,对于询问\(2\),扩展欧几里得算法解决,对于询问\(3\),\(BSGS\)算法解决。
对于第三个任务,一个细节要注意的是,题中保证了\(p\)为质数,却没保证\(a\)不是\(p\)的倍数。所以要特判\(a\)为\(p\)倍数的情况。
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
#define mset(name,val) memset(name,val,sizeof name)
long long t,k;
inline void input(void)
{
scanf("%lld%lld",&t,&k);
}
inline long long power(long long a,long long b,long long p)
{
long long res=1;
while (b)
{
if (1&b)res*=a,res%=p;
b>>=1;
a*=a,a%=p;
}
return res;
}
inline long long Exeuclid(long long a,long long &x,long long b,long long &y,long long c)
{
if (b==0){x=c/a,y=0;return a;}
else
{
long long p=Exeuclid(b,x,a%b,y,c);
long long x_=x,y_=y;
x=y_;y=x_-a/b*y_;
return p;
}
}
inline long long Euclid(long long a,long long b)
{
return b ? Euclid(b,a%b) : a;
}
inline long long Baby_Step_Giant_Step(long long a,long long b,long long p)
{
map < long long , long long > hash;hash.clear();
b%=p;long long t=(long long)sqrt(p)+1,mul=1;
for (int j=0;j<t;j++)
{
hash[ mul * b % p ] = j;
mul = mul * a % p;
}
if (a%p==0)return b==0 ? 1 : -1;
a = 1;
for (int i=0;i<=t;i++)
{
long long j = ( hash.find(a) != hash.end() ? hash[a] : -1 );
if (j>=0&&i*t-j>=0)return i*t-j;
a = a * mul % p;
}
return -1;
}
inline void solve(void)
{
long long y,z,p;
for (int i=1;i<=t;i++)
{
scanf("%lld%lld%lld",&y,&z,&p);
if (k==1)
printf("%lld\n",power(y,z,p));
if (k==2)
{
if (z%Euclid(y,p))
{
printf("Orz, I cannot find x!\n");
continue;
}
long long x_,y_;
Exeuclid(y,x_,p,y_,z);
printf("%lld\n",(x_%p+p)%p);
}
if (k==3)
{
long long ans=Baby_Step_Giant_Step(y,z,p);
if (ans==-1)
printf("Orz, I cannot find x!\n");
else printf("%lld\n",ans);
}
}
}
int main(void)
{
input();
solve();
return 0;
}
ExBSGS算法
顾名思义,该算法就是\(Baby\ Step\ Giant\ Step\)的拓展。对于方程\(a^x\equiv b(mod\ p)\),当\(a,p\)不互质的时候,我们可以使用该算法进行求解。
不难发现,当互质条件失去后,无解的情况也随之增加。经过严格的数学证明可以得到:当\(gcd(a,p)\not|b\)且\(b\not=1\)时,该方程无自然数解(转换成扩欧方程的有解性判定,由裴蜀定理可得)。
\(b=1\)的情况是需要特判的,\(x\)最小非负整数解为\(0\)。除了无解和该情况以外,我们可以用如下方法求解:
令\(d=gcd(a,p)\),将原式转换为 :$$a^{x-1}\ \frac{a}{d}\ \equiv \ \frac{b}{d}\ (mod\ \frac{p}{d})$$
设\(x_1=x-1,k_1=\frac{a}{d},b_1=\frac{b}{d},p_1=\frac{p}{d}\),则
\]
若能够求解该方程,则原方程的解\(x=x_1+1\)。
记录下\(k\),则这个方程的结构是可以进行同样的操作的。如此,不断缩小模数\(p\),直到\(gcd(a,p)=1\),得到方程$$k_1k_2...k_na^{x_n}\equiv b_n(mod\ p_n)$$
其中,\(gcd(a_n,p_n)=1\)。
令\(k=\prod_{i=1}^{n}k_i\),则$$k*a^{x_n}\equiv b_n(mod\ p_n)$$
直接使用\(BSGS\)算法求解该方程,则原方程的解\(x=x_n+n\)。
\(Code:\)
inline long long ExBSGS(long long a,long long b,long long p)
{
if (b==1)return 0;
long long cnt=0,d,k=1;
while ( ( d=Euclid(a,p) ) ^ 1 )
{
if (b%d)return -1;
b/=d,p/=d,++cnt;
k = k * (a/d) % p;
if (k==b)return cnt;
}
unordered_map < long long , long long > Hash;Hash.clear();
long long t=(long long)sqrt(p)+1,mul=1;
for (int j=0;j<t;j++)
{
Hash[ mul * b % p ] = j;
mul = mul * a % p;
}
for (int i=0;i<=t;i++)
{
long long j = ( Hash.find(k) != Hash.end() ? Hash[k] : -1 );
if (j>=0&&i*t-j+cnt>=0)return i*t-j+cnt;
k = k * mul % p;
}
return -1;
}
<后记>
『高次同余方程 Baby Step Giant Step算法』的更多相关文章
- POJ 3243 Clever Y (求解高次同余方程A^x=B(mod C) Baby Step Giant Step算法)
不理解Baby Step Giant Step算法,请戳: http://www.cnblogs.com/chenxiwenruo/p/3554885.html #include <iostre ...
- 解高次同余方程 (A^x=B(mod C),0<=x<C)Baby Step Giant Step算法
先给出我所参考的两个链接: http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4 (AC神,数论帝 扩展Baby Step Gian ...
- 数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)
什么叫高次同余方程?说白了就是解决这样一个问题: A^x=B(mod C),求最小的x值. baby step giant step算法 题目条件:C是素数(事实上,A与C互质就可以.为什么?在BSG ...
- 【学习笔记】Baby Step Giant Step算法及其扩展
1. 引入 Baby Step Giant Step算法(简称BSGS),用于求解形如\(a^x\equiv b\pmod p\)(\(a,b,p\in \mathbb{N}\))的同余方程,即著名的 ...
- HDU 2815 Mod Tree 离散对数 扩张Baby Step Giant Step算法
联系:http://acm.hdu.edu.cn/showproblem.php?pid=2815 意甲冠军: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...
- HDU 2815 扩展baby step giant step 算法
题目大意就是求 a^x = b(mod c) 中的x 用一般的baby step giant step 算法会超时 这里参考的是http://hi.baidu.com/aekdycoin/item/2 ...
- [置顶] hdu2815 扩展Baby step,Giant step入门
题意:求满足a^x=b(mod n)的最小的整数x. 分析:很多地方写到n是素数的时候可以用Baby step,Giant step, 其实研究过Baby step,Giant step算法以后,你会 ...
- POJ 2417 Discrete Logging ( Baby step giant step )
Discrete Logging Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3696 Accepted: 1727 ...
- 【POJ2417】baby step giant step
最近在学习数论,然而发现之前学的baby step giant step又忘了,于是去翻了翻以前的代码,又复习了一下. 觉得总是忘记是因为没有彻底理解啊. 注意baby step giant step ...
随机推荐
- Vue+localstrong登录注册,并保持登录状态
在router.js中添加meta区分 比如登录注册页面,不需要登录即可进入,那么我们把meta中的isLogin标志设置为false { //登录 path: '/login', component ...
- FlashFXP用到的功能
FlashFXP目前用到的个人理解就是: 一个公共空间 大家同时连接进来可以共享文件进去(该软件支持从屏幕上直接拖拽文件进来) 这里面页面之类的可以用手机进行访问(有利于调试) 第一步接收师哥给的软 ...
- 蓝桥杯刷题,第四界省赛B组
题头,本内容的题目和部分内容均来自博客:https://blog.csdn.net/ryo_218/article/details/79704030 ,在此感谢. 1. 题目标题:高斯日记大数学家高斯 ...
- C++进阶:新人易入的那些坑 --1.常量、常指针和指针常量
声明:以下内容B站/Youtube学习笔记,https://www.youtube.com/user/BoQianTheProgrammer/ Advanced C++. /* why use con ...
- npm、cnpm、yarn 安装删除异同
背景 一直觉得npm.cnpm.yarn的安装删除基本一样用哪个都行,不过俗话说的好,实践出真知,这里记录一下今天简单测试得到的结果总结. 可能会有错误,希望大家评论指正,十分感谢. 测试电脑系统:M ...
- js 原生: 身份证脱敏、唯一随机字符串uuid、对于高 index 元素的隐藏与显示
1. 对于高 index 元素的隐藏 与 显示 export const hideIndexEle = (cssStr)=>{ const player = getElementsByCss(c ...
- 邮件服务器 postfix
背景介绍 邮件服务器普遍需要一个主机名来使得mail from 以"账号@主机名"方式显示.由于外网上垃圾邮件太多,现在已不使用ip发邮件,很多网络供应商都会对来源不明的邮件进行限 ...
- HTML图片标签路径解析
img标签中src属性表示的是引用的图片路径,有两种路径类型: 1. 绝对路径 2. 相对路径. 绝对路径:使用图片在硬盘上的绝对位置来访问图片,通常是从根目录开始,向下一个目录一个目录的寻找. ...
- Python爬虫(2):urllib库
爬虫常用库urllib 注:运行环境为PyCharm urllib是Python3内置的HTTP请求库 urllib.request:请求模块 urllib.error:异常处理模块 urllib.p ...
- MVC编程模型
MVC 编程模型 MVC 是三个 ASP.NET 开发模型之一. MVC 是用于构建 web 应用程序的一种框架,使用 MVC (Model View Controller) 设计: Model(模型 ...