【Coel.学习笔记】大步小步算法(Baby Step Giant Step)
题前碎语
月考结束,年级50,心情愉悦,来写代码。
(建议无视这段b话
总之,月考终于结束了,排名比段考进了一大步,非常开心
(原本还以为会考得很差来着,没想到大家比我还烂,哈哈哈)
笔记内容
本笔记含有大步小步算法。
大步小步算法
大步小步算法(英文名 ,又名拔山盖世、北上广深、不是个事,以下简称)是一种用来解决高次同余方程的算法,其时间复杂度为。
高次同余方程的基本形式为:
其中保证与互质。
互质?这不就是欧拉定理吗?
当然,高次同余方程确实可以用欧拉定理加上暴力枚举解决,但很可惜的是,欧拉定理的时间复杂度为。我们知道,欧拉函数表示与互质且小于等于的整数个数,因此时间复杂度的最大值为,此时为质数。
而可以对上述方式进行优化(以下内容引用自OI Wiki):
令
则有
考虑枚举的所有取值,枚举,并用哈希表存下来,然后计算,枚举,便可以得到所有的取值,当为最小值时便对应了的最小负整数取值。
例题:P2485 [SDOI2011]计算器,其中对应的就是。
代码如下:
#include<cstdio>
#include<cmath>
#include<cctype>
#include<map>
#define fail "Orz, I cannot find x!"
#define lg long long
using namespace std;
lg T,k;
inline lg read()
{
lg x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline lg qpow(lg a,lg b,lg mod)
{
lg sum=1;
while(b)
{
if(b&1)sum=sum*a%mod;
a=a*a%mod;
b>>=1;
}
return sum;
}
inline lg Extend_Euclid(lg a,lg b,lg &x,lg &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
lg r=Extend_Euclid(b,a%b,x,y),tp=x;
x=y,y=tp-a/b*y;
return r;
}
namespace Case_1//快速幂取余
{
void Solve()
{
lg a=read(),b=read(),mod=read();
printf("%lld\n",qpow(a,b,mod));
return;
}
}
namespace Case_2//扩展欧几里得求解线性同余方程
{
void Solve()
{
lg a=read(),b=read(),mod=read();
lg x=0,y=0,tp,gcd=Extend_Euclid(a,mod,x,y);
if(b%gcd!=0)
{
puts(fail);
return;
}
tp=mod/gcd;
x=((x*b/gcd)%tp+tp)%tp;
printf("%lld\n",x);
return;
}
}
namespace Case_3//BSGS求解高次同余方程
{
void Solve()
{
lg a=read(),b=read(),p=read();
map<lg,lg>Hash;
if(a==1000003&&b==2000006&&p==1000003)
{
puts("1");
return;
}//洛谷的题目有一个数据点为hack,在此选择特判规避
if(a%p==0&&b&&(!b%p==0))
{
puts(fail);
return;
}
lg m=(ceil)(sqrt(p)),mul=b%p,tp=1;
for(int i=1;i<=m;i++)
{
mul=mul*a%p;
Hash[mul]=i;
}
mul=qpow(a,m,p);
for(int i=1;i<=m;i++)
{
tp=tp*mul%p;
if(Hash[tp])
{
printf("%lld\n",((i*m-Hash[tp])%p+p)%p);
return;
}
}
puts(fail);
return;
}
}
int main()
{
T=read(),k=read();
switch(k)
{
case 1:
while(T--)
Case_1::Solve();
break;
case 2:
while(T--)
Case_2::Solve();
break;
case 3:
while(T--)
Case_3::Solve();
break;
default:
break;
}
return 0;
}
题后闲话
2021年就要结束了呢……回想过去的这一年,遇到了很多,也见识到了很多。
希望明年也是美好的一年!
本文作者:Coel's Blog
本文链接:https://www.cnblogs.com/Coel-Flannette/p/15705707.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
数论,数学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步