首页 > 其他分享 >bsgs(扩展还没补)

bsgs(扩展还没补)

时间:2022-09-03 19:33:31浏览次数:58  
标签:没补 int 复杂度 扩展 cdot bsgs equiv mod

bsgs,北上广深,拔山盖世,蓝超巨星(blue super giant star)。大概是\(O(\sqrt n)\)求解模意义下离散对数的一个算法。经典的平衡复杂度思想。

离散对数,也就是长这样的一个东西:

\[a^x\equiv b\mod p \]

其中\(p\)是个质数,给你\(a,b,p,\)求最小的正整数\(x\)。

首先我们根据费马小定理知道\(a^x\)是个循环的,而且一个循环节是\(p-1\)。当然不一定是最小循环节。当然,我们不能暴力搞。这时我们就用到了一个重要思想:平衡复杂度的思想。

具体的,我们随便设个\(t\)(先在这挂着,取值一会再说),然后开始导柿子:

\[a^x\equiv b \mod p \]

设\(x=i\cdot t-j\)。

\[a^{i\cdot t-j}\equiv b \mod p \]

\[a^{i\cdot t}\equiv b\cdot a^j \mod p \]

对这个柿子,我们可以预处理每个\(a^j\),然后枚举\(i\)来找。显然\(j<t\)。当\(t=\sqrt n\)时,复杂度最低,为\(O(\sqrt n)\)。

知道原理之后代码其实很好写。

unordered_map<int,int>mp;
int bsgs(int a,int b){
	mp.clear();
	int sq=sqrt(mod)+1;
	int tmp=b;
	for(int i=0;i<sq;i++){
		mp[tmp]=i;//先预处理所有的j放到哈希表里 
		tmp=1ll*tmp*a%mod;
	}
	a=qpow(a,sq);
	if(!a)return b==0?1:-1;//特判一下有无解 
	for(int i=1,val=1;i<=sq;i++){//枚举所有i 
		val=1ll*val*a%mod;
		if(mp.find(val)!=mp.end())return i*sq-mp[val];//查找能不能找到对应的j 
	}
	return -1;
}

标签:没补,int,复杂度,扩展,cdot,bsgs,equiv,mod
From: https://www.cnblogs.com/gtm1514/p/16653399.html

相关文章