BSGS算法

Posted 小蒟蒻yyb的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BSGS算法相关的知识,希望对你有一定的参考价值。

BSGS算法

我是看着\\(ppl\\)的博客学的,您可以先访问\\(ppl\\)的博客

Part1 BSGS算法

求解关于\\(x\\)的方程

\\[y^x=z(mod\\ p) \\]

其中\\((y,p)=1\\)
做法并不难,我们把\\(x\\)写成一个\\(am-b\\)的形式
那么,原式变成了
\\(y^{am}=zy^b(mod\\ p)\\)
我们求出所有\\(b\\)可能的取值(0~m-1),并且计算右边的值
同时用哈希或者\\(map\\)之类的东西存起来,方便查询
对于左边,我们可以枚举所有可能的\\(a\\),然后直接查右边的值有没有相等的即可
复杂度是\\(O(max(m,p/m))\\)
不难证明\\(m=\\sqrt(p)\\)时复杂度最优

所以\\(bsgs\\)算法的复杂度是\\(O(\\sqrt(p))\\)

模板题:\\(SDOI2011\\) 计算器

关键代码:

int m=sqrt(p)+1;Hash.Clear();
for(RG int i=0,t=z;i<m;++i,t=1ll*t*y%p)Hash.Insert(t,i);
for(RG int i=1,tt=fpow(y,m,p),t=tt;i<=m+1;++i,t=1ll*t*tt%p)
{
	int k=Hash.Query(t);if(k==-1)continue;
	printf("%d\\n",i*m-k);return;
}

使用\\(map\\)会多个\\(log\\),在洛谷上我写的\\(Hash\\)目前是跑得最快的。。。

Part2 拓展BSGS

假设\\(gcd(y,p)\\neq 1\\)怎么办?
\\(d=gcd(y,p)\\)
将方程改写成等式形式

\\[y^x+kp=z \\]

发现此时的\\(z\\)必须要是\\(d\\)的倍数,否则无解。
因此,除掉\\(d\\)

\\[\\frac{y}{d}y^{x-1}+k\\frac{p}{d}=\\frac{z}{d} \\]

这样前面的\\(y/d\\)就是一个系数了,
不断检查\\(gcd(\\frac{z}{d},y)\\),一直除到互质为止
此时的形式就变成了

\\[\\frac{y^k}{d}y^{x-k}=\\frac{z}{d}(mod\\ \\frac{p}{d}) \\]

这样子\\(bsgs\\)求解之后在还原回去就行了。

模板:SPOJ Power Modulo Inverted
关键代码

void ex_BSGS(int y,int z,int p)
{
	if(z==1){puts("0");return;}
	int k=0,a=1;
	while(233)
	{
		int d=__gcd(y,p);if(d==1)break;
		if(z%d){NoAnswer();return;}
		z/=d;p/=d;++k;a=1ll*a*y/d%p;
		if(z==a){printf("%d\\n",k);return;}
	}
	Hash.clear();
	int m=sqrt(p)+1;
	for(int i=0,t=z;i<m;++i,t=1ll*t*y%p)Hash.Insert(t,i);
	for(int i=1,tt=fpow(y,m,p),t=1ll*a*tt%p;i<=m;++i,t=1ll*t*tt%p)
	{
		int B=Hash.Query(t);if(B==-1)continue;
		printf("%d\\n",i*m-B+k);return;
	}
	NoAnswer();
}

以上是关于BSGS算法的主要内容,如果未能解决你的问题,请参考以下文章

BSGS算法(大小步算法)

BSGS算法初探

BSGS算法及拓展

BSGS算法!

BSGS算法(大步小步算法)

bsgs(Baby Steps Giant Steps)算法