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();
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM