把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

BSGS 大步小步算法 求解高次同余方程【模板】

B a b y S t e p G i a n t S t e p BabyStepGiantStep BabyStepGiantStep 算法,缩写为 B S G S BSGS BSGS,即大步小步算法,,拔山盖世算法

用于求解同余方程 a x ≡ b ( m o d p ) a^x≡b(mod p) axb(modp) ,其中 ( a , p ) = 1 (a,p)=1 (a,p)=1

首先,我们可以先分析一下 x x x的范围(这个地方我觉得网上很多题解都没有讲到,只是列出了范围而已,或许在dalao们眼中这个是显而易见的

由于 ( a , p ) = 1 (a,p)=1 (a,p)=1,由费马小定理可得: a p − 1 ≡ 1 ( m o d p ) a^{p-1}≡1(mod p) ap11(modp),而 a 0 ≡ 1 ( m o d p ) a^0≡1(mod p) a01(modp),所以解的循环节小于 p p p,那么,如果选择暴力枚举的话,就应该从0到 p − 1 p-1 p1进行枚举,依次验证。

但是如果 p p p的范围比较大的话,就凉凉了,此时BSGS就应运而生


t = ⌊ p ⌋ t=⌊\sqrt{p}⌋ t=p
x x x表示为 x = i ∗ t − j x=i*t-j x=itj 0 ≤ i ≤ t 0≤i≤t 0it 0 ≤ j ≤ t 0≤j≤t 0jt
那么 a i ∗ t − j ≡ b ( m o d p ) a^{i*t-j}≡b(mod p) aitjb(modp)
两边同乘以 a j a^j aj a i ∗ t ≡ b ∗ a j ( m o d p ) a^{i*t}≡b*a^j(mod p) aitbaj(modp)
( a t ) i ≡ b ∗ a j ( m o d p ) (a^t)^i≡b*a^j(mod p) (at)ibaj(modp)

先枚举 j , 0 ≤ j ≤ t j,0≤j≤t j,0jt,把 b ∗ a j m o d p b*a^jmod p bajmodp插入到Hash表中
再枚举 i , 0 ≤ i ≤ t i,0≤i≤t i,0it,在Hash表中查 ( a t ) i m o d p (a^t)^imod p (at)imodp的值是否存在于Hash表中,若存在,则找到了一个解为 x = i ∗ t − j x=i*t-j x=itj
如果枚举完之后找不到,则方程无解


例题&板子: P O J 2417 D i s c r e t e L o g g i n g POJ2417 Discrete Logging POJ2417DiscreteLogging
传送门:POJ2417
B L = = N ( m o d P ) B^L == N (mod P) BL==N(modP求解最小的L

#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
using namespace std;
#define LL long long
LL a,b,p;
map<int,int> Hash;
map<int,bool> vis;
LL Pow(LL x,LL y)
{
	LL ans=1;
	while(y>0)
	{
		if(y&1) ans=(ans*x)%p;
		x=(x*x)%p;
		y>>=1;
	}
	return ans;
}
void Init()
{
	Hash.clear();
	vis.clear();
}
LL BSGS()
{
	Init();
	LL t=sqrt(p);
	b%=p;
	for(int j=0;j<=t;j++)
	{
		LL tmp=b*Pow(a,j)%p;
		Hash[tmp]=j;
		vis[tmp]=1;
	}
	a=Pow(a,t);
	for(int i=0;i<=t;i++)
	{
		LL tmp=Pow(a,i);
		if(vis[tmp])
		{
			int j=Hash[tmp];
			if(j>=0&&i*t-j>=0)
				return i*t-j;
		}
	}
	return -1;
}
int main()
{
	while(~scanf("%lld %lld %lld",&p,&a,&b))
	{//a^x%p==b%p
		LL ans=BSGS();
		if(ans==-1) printf("no solution\n");
		else printf("%lld\n",ans);
	}
	return 0;
}

posted @ 2022-04-27 21:05  Starlight_Glimmer  阅读(10)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end