BSGS算法解析
前置芝士:#
1.快速幂(用于求一个数的幂次方)
2.STL里的map(快速查找)
详解#
BSGS 算法适用于解决高次同余方程
由费马小定理可得 x <= p-1
我们设 至于为什么写,下文会讲到。
那么就可以用 表示出来。
即 x =
移项可得 其中 t =
这也就是我们为什么把用 来表示。
因为改为加后,移项后要求逆元,就会变得很麻烦。
这样,我们就可以枚举每个和,来判断左右两边得值是否相等就行了。
首先,我们可以枚举j 将 放入map中。
然后,从小到大枚举,在哈希表中,找到最大的满足 其中 t =
若存在就是方程的解
关于上文中,为什么要设
是为了保证BSGS的复杂度,是左右两边的数尽可能的均匀。
例题#
模板题,水过去了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
#define LL long long
int a,b,p;
LL ksm(LL a, LL b)
{
LL res = 1;
for(; b; b >>= 1)
{
if(b & 1) res = res * a % p;
a = a * a % p;
}
return res;
}
int BSGS(int a,int b,int p)
{
map<LL,int> hash; hash.clear();
int m = (int)sqrt(p);
for(int i = 0; i <= m; i++)
{
LL val = ksm(a,i) * b % p;//b * a ^ i
hash[val] = i;//放入map中
}
a = ksm(a,m);//a ^ m
for(int i = 0; i <= m; i++)
{
LL val = ksm(a,i);//(a^m)^i
int j = hash.find(val) == hash.end() ? -1 : hash[val];//如果没有j就为-1
if(j >= 0 && i * m - j >= 0) return i * m - j;//找到一组解
}
return -1;
}
int main()
{
scanf("%d%d%d",&p,&a,&b);
LL ans = BSGS(a,b,p);
if(ans == -1) cout<<"no solution"<<endl;
else printf("%lld\n",ans);
return 0;
}
一道很多算法综合在一起的模板题,水过去了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define LL long long
int t,opt,a,b,p,x,y;
inline int read()
{
int s = 0, w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10+ch -'0'; ch = getchar();}
return s * w;
}
LL gcd(LL a, LL b)
{
if(b == 0) return a;
else return gcd(b,a%b);
}
LL ksm(LL a, LL b)//快速幂
{
LL res = 1;
for(; b; b >>= 1)
{
if(b & 1) res = res * a % p;
a = a * a % p;
}
return res;
}
LL exgcd(int a,int b, int &x,int &y)//扩展欧几里得
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
LL gcd = exgcd(b,a%b,y,x);
y -= a / b * x;
return gcd;
}
LL BSGS(LL a,LL b,LL p)//BSGS
{
map<LL,int> hash; hash.clear();
int m = (int) sqrt(p);
b % p;
for(int i = 0; i <= m; i++)
{
LL tmp = ksm(a,i) * b % p;
hash[tmp] = i;
}
a = ksm(a,m);
if(a == 0) return b == 0 ? 1 : -1;//特判当a为0的情况
for(int i = 0; i <= m; i++)
{
LL tmp = ksm(a,i);
int j = hash.find(tmp) == hash.end() ? -1 : hash[tmp];
if(j >= 0 && i * m - j >= 0) return i * m - j;
}
return -1;
}
int main()
{
t = read(); opt = read();
while(t--)
{
a = read(); b = read(); p = read();
if(opt == 1)
{
LL ans = ksm(a,b);
printf("%lld\n",ans);
}
if(opt == 2)
{
LL k = exgcd(a,p,x,y);
if(b % k) cout<<"Orz, I cannot find x!"<<endl;
else printf("%lld\n",(x * (b/k) % p + p)%p);
}
if(opt == 3)
{
LL ans = BSGS(a,b,p);
if(ans == -1) cout<<"Orz, I cannot find x!"<<endl;//无解情况
else printf("%lld\n",ans);
}
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· 程序员常用高效实用工具推荐,办公效率提升利器!
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 【译】WinForms:分析一下(我用 Visual Basic 写的)