BSGS&ExBSGS
求解形如
[a^xequiv bpmod p
]
的高次同余方程
BSGS
假装(gcd(a,p)=1)。
设(m=lceilsqrt p ceil)
然后把(x)分解成
[x=i*m+j
]
的形式。
[a^xequiv bpmod p
]
[a^{i*m+j}equiv bpmod p
]
[a^{im}equiv b/a^jpmod p
]
这时我们发现,(1≤j≤m-1),也就是说枚举(j)是非常简单的。
这样我们就可以把(m-1)个(j)全都存起来,存到哈希表中,然后枚举(i),这样就可以在(O(sqrt n + log (n)))的时间内求出解了。(分块 + map)
(时间复杂度是wyh在网上找的,自己不会证qwq
ExBSGS
刚刚我们假装(gcd(a,p)=1),那要是没有这个条件怎么办呢?
很简单,我们只要通过把两边同时除以 他们的 gcd 就好啦qwq
设(g=gcd(a,p)),如果(g ot| b),显然如果(p=1)则(x=0),否则方程无解
我们就得到
[a^{x-1}*frac{a}{g}equiv frac{b}{g}pmod {frac{p}{g}}
]
[a^{x-1}equiv frac{b}{a}pmod {frac{p}{g}}
]
这样一直做下去,直到(g=1)为止。
有一个误区(对于我这种蒟蒻)就是(a)和(b/g)不一定互质。这是zzy学长告诉wyh的qwq,还是学长好啊qwq。
好感动啊。。。
Code
typedef long long ll;
map<ll,ll> ma;
inline ll bsgs(ll a,ll b)//解a^x同余b (%mod)
{
a%=mod;b%=mod;
ma.clear();
ll m=ll(sqrt(mod+1)),e=1;
for(int j=0;j<m;++j)
{
if(!ma.count(e)) ma[e]=j;
e=e*a%mod;
}
if(gcd(e,mod)!=1) return -1;
ll inv=inverse(e);//逆元
for(int i=0;i<m;++i)
{
if(ma.count(b)) return i*m+ma[b];
b=b*inv%mod;
}
return -1;
}